使用不带分组字符的数字过滤JTable(千位分隔符)

时间:2014-11-25 11:48:19

标签: java swing jtable rowfilter

我正在尝试过滤包含带数字的列的JTable中的行。

到目前为止,过滤工作正在进行,但它会对包括千位分隔符在内的数字进行过滤。例如,如果一行中有一个数字为25689的行,并且我尝试过滤此行,则必须使用“25.689”。因此,似乎在过滤之前执行了格式化。

我试图设置一个自己的默认渲染器,但是没有分隔符显示数字,但过滤是相同的。

修改

我添加了一个重新创建问题的完整示例:

public class GroupingTest {

    JFrame frame= null;
    Container pane= null;
    JTextField tf=null;
    JXTable table=null;

    public void searchTable() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {                       
                    final String searchEx = "(?i)"
                                          + Pattern.quote(tf.getText());

                    final RowFilter<TableModel, Object> filter;
                    filter = RowFilter.regexFilter(searchEx);    
                    table.setRowFilter(filter);
                    //packAll in edt
                    Utility.packTableView(table);                       
                } catch (final Exception e) {
                    return;
                }
            }
        });
    }

    public void createTable() {
        frame = new JFrame();
        pane=frame.getContentPane();

        tf = new JTextField();
        tf.setPreferredSize(new Dimension(200,25));

        tf.getDocument().addDocumentListener(new DocumentListener() {

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

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

            @Override
            public void changedUpdate(final DocumentEvent e) {
                searchTable();
            }
        });

        String[] columnHeaders = {"long","strings"};

        DefaultTableModel $model = new DefaultTableModel(columnHeaders, 0) {
            @Override
            public Class<?> getColumnClass(final int $col) {
                if($col == 0) {
                    return Long.class;
                } else if($col == 1){
                    return String.class;
                } else {
                    return Object.class;
                }
            }
        };

        table = new JXTable($model);

        table.setDefaultRenderer(Long.class, new DefaultTableCellRenderer() {

            @Override
            public java.awt.Component getTableCellRendererComponent(final JTable $table,
                    final Object $value, final boolean $isSelected, final boolean $hasFocus, final int $row,
                    final int $column) {
                super.getTableCellRendererComponent($table, $value, $isSelected, $hasFocus, $row, $column);

                if ($value instanceof Long) {
                    this.setHorizontalAlignment(SwingConstants.RIGHT);
                }

                return this;
            }
        });

        Object[] line1 = {new Long(23345),"asdf"};
        $model.addRow(line1);
        Object[] line2 = {new Long(3),"dfw"};
        $model.addRow(line2);

        pane.add(tf,BorderLayout.NORTH);
        pane.add(new JScrollPane(table),BorderLayout.CENTER);

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(300,200));
        frame.pack();
        frame.setVisible(true);             
    }

    public static void main(String[] args) {        
        GroupingTest gt = new GroupingTest();
        gt.createTable();    
    }    
}

1 个答案:

答案 0 :(得分:3)

  

到目前为止过滤工作正在进行,但它会过滤包括千位分隔符在内的数字。

当值的格式干扰分拣机和过滤器的预期功能时,是时候检查表模型中的getColumnClass(int columnIndex)是否正在检索相应的类(在本例中为{{ 1}})。

默认Double这种方法的实现会返回使用AbstractTableModel方法呈现的Object.class(这就是为什么你会看到千位分隔符)并且可能根据字符串表示。 toString()的子类(例如AbstractTableModel)继承此实现,因此应该覆盖此方法。例如,假设您的表格型号为DefaultTableModel,第一列为DefaultTableModel

Double

有关详细信息,请参阅Sorting and Filtering教程的How to Use Tables部分。

更新

鉴于你的新MVCE,现在很清楚你想要实现什么。我开始说我错误地假设您的表格模型包含DefaultTableModel model = new DefaultTableModel() { @Override public Class<?> getColumnClass(int columnIndex) { return columnIndex == 0 ? Double.class : super.getColumnClass(columnIndex); } }; 而不是Double,这对覆盖Long方法没有任何影响(无论如何都应该这样做)但它会在最终解决方案中略有不同。

现在,要明确说明要求,您需要过滤该列:

  • 用户输入一个(长)包括分组字符。
  • 用户输入数字,不带分组字符。
  • 值的字符串表示形式包含用户键入的子字符串。

为了实现这一目标,我使用自定义getColumnClass()而不是像您在示例中那样使用正则表达式过滤器。这是为了控制用户键入的字符串并检查上面列出的三个条件。我设法修改了您的RowFilter以满足要求。注意:我已将查询的字符串作为参数包含在此方法中,以便将searchTable()文本字段保留在实现之外。请参阅以下代码:

tf

流量或多或少如下:

  1. 如果查询长度为0,则让过滤器为private void searchTable(final String query) { RowFilter<TableModel, Integer> filter = null; if (query.length() > 0) { filter = new RowFilter<TableModel, Integer>() { @Override public boolean include(RowFilter.Entry<? extends TableModel, ? extends Integer> entry) { for (int i = 0; i < entry.getValueCount(); i++) { String stringValue = entry.getStringValue(i); Object entryValue = entry.getValue(i); String numberString = entryValue instanceof Long ? String.valueOf(entryValue) : ""; if (stringValue.contains(query) || numberString.contains(query)) { return true; } } return false; } }; } table.setRowFilter(filter); } 。这意味着表格不会被过滤,所有重试都将被包含在内。

  2. 如果不是(1)那么准备一个新的过滤器,迭代整行,询问条目 的字符串表示是否为entry包含查询的String。虽然那些看起来可能与他们不同,但因为Entry#getStringValue(int index)可能(实际上)检索的值不同于String#valueOf(entry#getValue(int index))。在这种情况下,第一个检索Long包括分组分隔符(或者如果您愿意,则格式化),而第二个检索Long而根本没有格式化(这意味着,没有分组分隔符)。

  3. 在任何一种情况下都将过滤器应用于表格。

  4. 我希望这个想法足够清楚。如果要过滤null,则必须稍微调整一下,因为Double包含十进制(不是分组)分隔符,您可能希望在检查它是否包含查询的字符串之前将其删除。