1

我有一个与这个非常相似的 JTable。

http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting

桌子

我已经设法在它上面设置了一个普通的过滤器(一个搜索功能)并且效果很好。我想要一个按钮,该按钮将立即仅显示选中 Vegetarian 的行。

好的,现在感谢@peeskillet 和@HovercraftFullOfEels 提供的帮助,这是我的问题的解决方案:

final TableRowSorter<MovieReviewTableModel> rowSorter = new TableRowSorter<MovieReviewTableModel>(tableModel);



// custom RowFilter 
            RowFilter<MovieReviewTableModel, Integer> filter = new RowFilter<MovieReviewTableModel, Integer>()
            {
                // include method returns true to show the row and false to not show it
                @Override
                public boolean include(RowFilter.Entry<? extends MovieReviewTableModel, ? extends Integer> entry)
                {
                    int modelRow = entry.getIdentifier(); //row index
                    boolean checked = ((Boolean)entry.getModel().getValueAt(modelRow, 3)).booleanValue();
                    System.out.println(checked); // to test the values coming through
                    return checked;
                }

            };

            table.setRowSorter(rowSorter);

            JButton onlyFeatured = new JButton("Only show Featured");
            threeButtonPanel.add(onlyFeatured);

            onlyFeatured.addActionListener(new ActionListener()
            {
                public void actionPerformed(ActionEvent event)
                {
                    rowSorter.setRowFilter(filter);
                }
            });

有用!非常感谢你们,我欠你们酒水什么的。:D

4

2 回答 2

3

让我们重温一下教程如何使用表格:排序和过滤

除了对结果重新排序之外,表格排序器还可以指定将显示哪些行。这称为过滤。使用javax.swing.RowFilter对象TableRowSorter实现过滤。实现了几个创建常见类型过滤器的工厂方法。RowFilter

要看的东西:

  • TableRowSorter. - 我们知道我们需要这个。
  • 哦,他们给了我们一个RowFilter文档链接。让我们在新的浏览器选项卡中打开它。
  • 但首先最后一行RowFilter实现了几个创建常见类型过滤器的工厂方法”。. 我们可能应该看看那些“常见的种类”是什么。

行过滤器 javadoc

  • 静态方法 - andFilter, dateFilter, notFilter, numberFilter, orFilter, regexFilter. 好的,我regexFilter从教程中认出了。但其他那些,仅凭他们的名字,听起来不太有希望。也许我们应该实现我们自己的。让我们看看 javadoc 的其余部分

javax.swing.RowFilter<M,I>

类型参数:
M- 模型的类型;例如PersonModel
I- 标识符的类型;当使用TableRowSorter这将是Integer

好的,从这里我们知道两件事。当我们创建我们的 customRowFilter时,我们应该传递一个TableModel类型作为第一个参数,并用 typeInteger来表示行号。

RowFilter用于从模型中过滤掉条目,以便它们不会显示在视图中。例如,与 aRowFilter关联的 aJTable可能只允许包含具有特定字符串的列的行。条目的含义取决于组件类型。例如,当过滤器与 关联时JTable,条目对应于行;当与 a 关联时JTree,条目对应于一个节点。

子类必须重写该include方法以指示条目是否应显示在视图中。该Entry参数可用于获取该条目中每一列的值

因此,基于这两个段落,我们知道RowFilter用于过滤掉视图中不需要的行,如果我们创建自己的,我们将需要重写该include方法以返回是否应显示行. 并且该include方法还将有一个Entry参数,在确定哪一行不返回 true 时,我们可以从中获取我们可能感兴趣的细节。这是javadoc给我们的基本示例(指南)

RowFilter<TableModel, Integer> filter = new RowFilter<TableModel, Integer>() {
    @Override
    public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry) {
        // do your logic here to return true or false.
    }
};

很酷,但是这个RowFilter.Entry类是什么,它可以为我们提供什么有趣的信息?让我们看一下javadoc

我们可以看到的一件有趣的事情是getModel()方法。从中我们可以得到我们的表格模型。所以让我们完成实现

private static final int CHECKBOX_COLUMN = 4;
...
RowFilter<TableModel, Integer> filter = new RowFilter<TableModel, Integer>() {
    @Override
    public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry) {
        int modelRow = entry.getIdentifier();
        Boolean checked = (Boolean)entry.getModel().getValueAt(modelRow, CHECKBOX_COLUMN);
        return checked;
    }
};

也不多吧。现在剩下的就是将过滤器设置为排序器,正如您已经从 Oracle 教程中学到的那样,使用正则表达式过滤器。

这是一个填充演示代码。它没有实现ActionListener按钮按下。我不想为你做一切。您应该有足够的信息来自己处理:-D 快乐学习!

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowFilter;
import javax.swing.SwingUtilities;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class TableBooleanFilterDemo {

    public TableBooleanFilterDemo() {
        JTable table = getTable();
        TableRowSorter<TableModel> rowSorter = new TableRowSorter<>(table.getModel());
        RowFilter filter = getRowFilter();
        rowSorter.setRowFilter(filter);
        table.setRowSorter(rowSorter);

        JFrame frame = new JFrame();
        frame.add(new JScrollPane(table));
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    }
    
    private static final int CHECKBOX_COLUMN = 4;

    private RowFilter getRowFilter() {
        RowFilter<TableModel, Integer> filter = new RowFilter<TableModel, Integer>() {
            @Override
            public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry) {
                int modelRow = entry.getIdentifier();
                Boolean checked = (Boolean)entry.getModel().getValueAt(modelRow, CHECKBOX_COLUMN);
                return checked;
            }
        };
        return filter;
    }

    private JTable getTable() {
        Object[][] data = {
            {"Kathy", "Smith",
                "Snowboarding", new Integer(5), new Boolean(false)},
            {"John", "Doe",
                "Rowing", new Integer(3), new Boolean(true)},
            {"Sue", "Black",
                "Knitting", new Integer(2), new Boolean(false)},
            {"Jane", "White",
                "Speed reading", new Integer(20), new Boolean(true)},
            {"Joe", "Brown",
                "Pool", new Integer(10), new Boolean(false)}
        };
        String[] columnNames = {"First Name",
            "Last Name",
            "Sport",
            "# of Years",
            "Vegetarian"};
        return new JTable(new DefaultTableModel(data, columnNames) {
            public Class getColumnClass(int c) {
                return getValueAt(0, c).getClass();
            }
        });
    }
    
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run() {
                new TableBooleanFilterDemo();
            }
        });
    }
}

老实说,我从来没有实现自己的RowFilter,但以上是我在尝试学习新东西时几乎经历的过程。我花了更长的时间来写这个答案,然后学习如何去做。必须学会阅读文档,而不仅仅是教程。教程是一个很好的起点,但是一旦你遇到更复杂的问题,你就需要深入挖掘。与您想学习的任何新技术一样。

于 2014-09-20T14:51:48.307 回答
2

你的 RowFilter 太简单了,你需要给它更多的重量,更多的肉。RowFilter API实际上有一小部分非常有用的示例代码可以帮助您。例如,我使用该代码帮助我创建了一个非常简单但可行的 RowFilter:

import java.awt.BorderLayout;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;

public class Foo {
   public static void main(String[] args) {
      String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" };
      JComboBox<String> petCombo = new JComboBox<>(petStrings);
      String[] columnNames = {"Name", "Animal", "Male", "Delete"};
      Object[][] data = {
          {"Tweetie", petStrings[0], false, null},
          {"Sylvester", petStrings[1], true, null},
          {"Lassie", petStrings[2], false, null},
          {"Peter", petStrings[3], true, null},
          {"Arnold", petStrings[4], true, null}
      };

      final MyTableModel model = new MyTableModel(data, columnNames);
      final JTable table = new JTable(model);
      table.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(petCombo));


      final TableRowSorter<MyTableModel> sorter = new TableRowSorter<MyTableModel>(model);
      final RowFilter<MyTableModel,Integer> maleSexFilter = new RowFilter<MyTableModel,Integer>() {
         public boolean include(Entry<? extends MyTableModel, ? extends Integer> entry) {
            MyTableModel personModel = entry.getModel();
            boolean maleSex = ((Boolean) personModel.getValueAt(entry.getIdentifier(), 2)).booleanValue();
           return maleSex;
          }
        };

      sorter.setRowFilter(null);
      table.setRowSorter(sorter);

      JToggleButton showMalesButton = new JToggleButton("Show Males");
      showMalesButton.addItemListener(new ItemListener() {

         @Override
         public void itemStateChanged(ItemEvent iEvt) {
            if (iEvt.getStateChange() == ItemEvent.SELECTED) {
               System.out.println("selected!");
               sorter.setRowFilter(maleSexFilter);
            } else {
               sorter.setRowFilter(null);
            }
         }
      });

      JPanel bottomPanel = new JPanel();
      bottomPanel.add(showMalesButton);

      JPanel panel = new JPanel(new BorderLayout());
      panel.add(new JScrollPane(table), BorderLayout.CENTER);
      panel.add(bottomPanel, BorderLayout.PAGE_END);

     JOptionPane.showMessageDialog(null, panel);
   }
}

@SuppressWarnings("serial")
class MyTableModel extends DefaultTableModel {
   public MyTableModel(Object[][] data, String[] columnNames) {
      super(data, columnNames);
   }

   @Override
   public Class<?> getColumnClass(int columnIndex) {
      if (columnIndex == 2) {
         return Boolean.class;
      }
      return super.getColumnClass(columnIndex);
   }
}

过滤器代码为:

  final RowFilter<MyTableModel,Integer> maleSexFilter = new RowFilter<MyTableModel,Integer>() {
     public boolean include(Entry<? extends MyTableModel, ? extends Integer> entry) {
        MyTableModel personModel = entry.getModel();
        boolean maleSex = ((Boolean) personModel.getValueAt(entry.getIdentifier(), 2)).booleanValue();
       return maleSex;
      }
    };

我所做的就是获取第二列保存的布尔值,由 entry.getIdentifier() 确定的行,并返回该值。如果为真,则它被选中。

于 2014-09-20T14:45:46.787 回答