用于过滤列表的组件

时间:2015-02-20 04:27:13

标签: java swing list

什么是适合创建可过滤列表的Java Swing组件,如下所示?

2 个答案:

答案 0 :(得分:4)

使用单个列JTable可以轻松完成此类过滤。表具有内置功能,可添加RowSorter

  

..提供了排序和过滤的基础。

另见How to Use Tables: Sorting and Filtering

以下是过滤字体系列名称的示例:

enter image description here

左边是一个更多的列表'组件,而右侧显示的组件显然是一个表。

代码

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;
import javax.swing.event.*;
import javax.swing.text.Document;
import javax.swing.table.TableRowSorter;

public class FontFilter {

    private JComponent ui = null;
    JTextField filterText;
    TableRowSorter sorter;

    FontFilter(boolean listLike) {
        initUI(listLike);
    }

    public void initUI(boolean listLike) {
        if (ui != null) {
            return;
        }

        ui = new JPanel(new BorderLayout(4, 4));
        ui.setBorder(new EmptyBorder(4, 4, 4, 4));

        GraphicsEnvironment ge
                = GraphicsEnvironment.getLocalGraphicsEnvironment();
        String[] fonts = ge.getAvailableFontFamilyNames();
        String[][] tableData = new String[fonts.length][1];
        for (int i = 0; i < fonts.length; i++) {
            tableData[i][0] = fonts[i];
        }
        String[] header = {"Fonts"};
        JTable table = new JTable(tableData, header);
        if (listLike) {
            Dimension d = table.getPreferredScrollableViewportSize();
            table.setPreferredScrollableViewportSize(new Dimension(d.width/2,d.height));
            table.setShowGrid(false);
            table.setTableHeader(null);
            table.setFillsViewportHeight(true);
        }
        ui.add(new JScrollPane(table));
        sorter = new TableRowSorter(table.getModel());
        table.setRowSorter(sorter);

        filterText = new JTextField(10);
        ui.add(filterText, BorderLayout.PAGE_START);
        Document doc = filterText.getDocument();
        DocumentListener listener = new DocumentListener() {

            @Override
            public void insertUpdate(DocumentEvent e) {
                newFilter();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                newFilter();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                newFilter();
            }
        };
        doc.addDocumentListener(listener);
    }

    private void newFilter() {
        RowFilter rf = null;
        //If current expression doesn't parse, don't update.
        try {
            rf = RowFilter.regexFilter(filterText.getText(), 0);
        } catch (java.util.regex.PatternSyntaxException e) {
            return;
        }
        sorter.setRowFilter(rf);
    }

    public JComponent getUI() {
        return ui;
    }

    public static void main(String[] args) {
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (Exception useDefault) {
                }
                FontFilter o1 = new FontFilter(true);
                FontFilter o2 = new FontFilter(false);

                JFrame f = new JFrame("Font Filter");
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                f.setLocationByPlatform(true);

                f.add(o1.getUI(), BorderLayout.LINE_START);
                f.add(o2.getUI(), BorderLayout.CENTER);
                f.pack();
                f.setMinimumSize(f.getSize());

                f.setVisible(true);
            }
        };
        SwingUtilities.invokeLater(r);
    }
}

答案 1 :(得分:1)

如果您想要或只需要使用标准的Swing组件,那么@AndrewThompson描述的方法就是您的选择。

但是,如果您能够使用第三方库,那么SwingX项目中包含的JXList组件就是一个很好的选择。此组件是JList扩展程序,可以对其内容进行排序和过滤以及其他有趣的功能(请查看SwingLabs Demos)。

以下代码段是使其有效的基础:

JXList list = new JXList(listModel);
list.setAutoCreateRowSorter(true);

这足以创建和安装RowSorter<ListModel, Integer>实例作为列表的行分类器,可以通过调用getRowSorter()方法来检索它。此方法返回的实际对象是ListSortController,它继承自DefaultRowSorter并且还实现了非标准SortController接口。

重要的是要记住这个类层次结构,因为它可以以不同的方式提供RowFilter。以下所有备选方案均假设行分类器是自动创建的。

注意: IMO第一种方法是首选方法,因为我们可以委托压缩行分类器的脏工作为组件提供行过滤器。

1。直接在列表

上设置行过滤器
list.setRowFilter(rowFilter);

这是设置行过滤器的便捷方法。但是,合同要求实际列表的行分类器是SortController兼容的实例。否则setRowFilter(...)电话无效。

2。将行分类器转换为SortController

SortController<ListModel> sortController 
        = (SortController<ListModel>)list.getRowSorter();
sortController.setRowFilter(rowFilter);

SortController接口提供了一种方法来设置行过滤器,该行过滤器用于绕过方法#1中的行过滤器。

3。将行分类器转换为DefaultRowSorter

DefaultRowSorter<ListModel, Integer> sorter 
        = (DefaultRowSorter<ListModel, Integer>)list.getRowSorter();
sorter.setRowFilter(rowFilter);

此方法与我们使用JTable时的方法相同。

实施例

以下是一个关于使用JXList进行过滤的简单演示。请再次查看SingLabs Demos以获取更好的示例。

import java.awt.BorderLayout;
import java.awt.GraphicsEnvironment;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.ListModel;
import javax.swing.RowFilter;
import javax.swing.SwingUtilities;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import org.jdesktop.swingx.JXList;    

public class FilterListDemo {

    private JXList list;

    private void createAndShowGui() {

        final JTextField filterText = new JTextField(30);
        filterText.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                FilterListDemo.this.createFilter(filterText.getText(), false);
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                FilterListDemo.this.createFilter(filterText.getText(), false);
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                FilterListDemo.this.createFilter(filterText.getText(), false);
            }
        });

        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        String[] fonts = ge.getAvailableFontFamilyNames();

        list = new JXList(fonts);
        list.setAutoCreateRowSorter(true);

        JPanel content = new JPanel(new BorderLayout(8,8));
        content.add(filterText, BorderLayout.PAGE_START);
        content.add(new JScrollPane(list), BorderLayout.CENTER);
        content.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));

        JFrame frame = new JFrame("Filter List Demo");
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.add(content);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }

    private void createFilter(String text, final boolean caseSensitive) {

        final String filterText = caseSensitive ? text : text.toUpperCase();

        list.setRowFilter(new RowFilter<ListModel, Integer>() {
            @Override
            public boolean include(RowFilter.Entry<? extends ListModel
                    , ? extends Integer> entry) {

                String entryValue = caseSensitive 
                        ? entry.getStringValue(0) 
                        : entry.getStringValue(0).toUpperCase();

                return filterText == null 
                        || filterText.trim().isEmpty() 
                        || entryValue.contains(filterText.trim());
            }
        });
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new FilterListDemo().createAndShowGui();
            }
        });
    }
}