有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java筛选器JTable,带有不带分组字符的数字(千分位)

我正在尝试筛选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) 个答案

  1. # 1 楼答案

    The Filtering is working so far, but it filters over the numbers including the thousands-separators.

    当值的格式干扰了分类器和过滤器的预期功能时,就应该检查表模型中的getColumnClass(int columnIndex)是否正在检索适当的类(在本例中为Double

    默认情况下,这种方法的AbstractTableModel实现返回Object.class,它是使用toString()方法呈现的(这就是为什么您会看到千位分隔符),并且可能也会根据字符串表示进行过滤。AbstractTableModel的子类(如DefaultTableModel)继承此实现,因此应重写此方法。例如,假设您的表模型是DefaultTableModel,第一列是Double

    DefaultTableModel model = new DefaultTableModel()  {
        @Override
        public Class<?> getColumnClass(int columnIndex) {
            return columnIndex == 0 ? Double.class 
                                    : super.getColumnClass(columnIndex);
        }
    };
    

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

    更新

    考虑到你的新MVCE,现在很清楚你想要实现什么。我开始说,我错误地假设您的表模型持有的是Double,而不是Long,这对重写getColumnClass()方法没有影响(无论如何都应该这样做),但对最终的解决方案会有轻微的影响

    现在,为了明确说明需求,您需要筛选该列:

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

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

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

    流量大致如下所示:

    1. 如果查询长度为0,则让筛选器为null。这意味着该表不会被过滤,所有租金都将包括在内

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

    3. 在这两种情况下,都将筛选器应用于表

    我希望这个想法足够清楚。如果要筛选Double,则必须稍微调整它,因为String.valueOf(double)包含十进制(非分组)分隔符,您可能希望在检查它是否包含查询的字符串之前删除它