【问题标题】:Component for filtering a list用于过滤列表的组件
【发布时间】:2015-02-20 04:27:12
【问题描述】:

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

【问题讨论】:

    标签: java swing list


    【解决方案1】:

    这种类型的过滤使用单个列JTable 最容易完成。表格具有添加 RowSorter 的内置功能:

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

    另见How to Use Tables: Sorting and Filtering

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

    左侧是一个更像“列表”的组件,而右侧显示的组件显然是一个表格。

    代码

    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);
        }
    }
    

    【讨论】:

    • RowSorter 可以比从任何对象中获取对象数组、按条件排序、将排序后的数组返回给模型更快,比在运行时在模型中排序更快,除重要说明外,JComboBox 模型/JList(其中项目数超过 999,删除/At/All,替换,在这里插入几次关于此问题),如果您想从一个代码中操作整个数据/对象,则会出现性能问题线路、方法
    • 现在我不记得正确的方法(性能问题),如果从过滤开始,然后应用排序或直接过滤排序视图,不知道
    【解决方案2】:

    如果您想或必须只使用标准 Swing 组件,那么@AndrewThompson 描述的方法是可行的方法。

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

    下面的sn-p是让它工作的基础:

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

    这足以创建和安装一个RowSorter&lt;ListModel, Integer&gt; 实例作为列表的行排序器,可以通过调用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();
                }
            });
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 2013-05-03
      相关资源
      最近更新 更多