用于过滤列表的组件

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

这种types的过滤最容易使用单个列JTable 。 一个表具有内置function来添加RowSorter ,其中:

为sorting和过滤提供了依据

另请参见如何使用表:sorting和筛选 。

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

在这里输入图像描述

左边是更多的“清单查看”组件,右边则显示了一个清晰可见的组件。

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

如果你想要或者不得不使用标准的Swing组件,那么@AndrewThompson描述的方法就是要走的路。

但是如果你能够使用第三方库,那么SwingX项目中包含的JXList组件就是一个很好的select。 这个组件是一个JList扩展,并提供sorting和过滤其内容以及其他有趣function(检查SwingLabs演示 )的function。

以下片段是使其工作的基础:

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

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

记住这个类层次是很重要的,因为可以用不同的方式提供一个RowFilter 。 以下所有替代方法假定行分拣机是自动创build的。

注意: IMO第一种方法是首选方法,因为我们可以委托向下排放行分拣机的脏工作来为组件提供行filter。

1.直接在列表中设置行筛选器

 list.setRowFilter(rowFilter); 

这是设置行filter的一种方便方法。 但是合同要求实际列表的行分类器是一个SortController兼容的实例。 否则, setRowFilter(...)调用不起作用。

2.将行分拣机转换为SortController

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

SortController接口提供了一种方法来设置用于旁路方法#1中的行filter的行filter。

3.将行分拣机转换为DefaultRowSorter

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

这个方法与我们使用JTable方法相同。

这里是一个关于使用JXList过滤的简单演示。 请再次检查SingLabs演示以获取更好的示例。

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