【问题标题】:Why does my JTable sort an integer column incorrectly?为什么我的 JTable 对整数列进行错误排序?
【发布时间】:2020-07-26 11:19:29
【问题描述】:

我有一个使用 DefaultTableModel 的 JTable,并且允许在用户单击列标题时进行排序。但是,当用户单击具有整数类型数据的列的标题时,它不会正确排序。它似乎是按字符串而不是整数类型排序的。

这是我将数据实际添加到表中的代码部分:

        DefaultTableModel aModel = (DefaultTableModel) mainView.logEntryTable.getModel();
                    ResultSetMetaData rsmd;             try {
            mainView.logEntriesTableModel.setRowCount(0);
            rsmd = rs.getMetaData();

            int colNo = rsmd.getColumnCount();
            while(rs.next()){
                Object[] objects = new Object[colNo];
                for(int i=0;i<colNo;i++){
                    objects[i]=rs.getObject(i+1);
                }
                aModel.addRow(objects);
                count++;
            }
            mainView.logEntryTable.setModel(aModel);
            mainView.logEntryTable.getColumnModel().getColumn(0).setMaxWidth(80);

所以我尝试覆盖该方法并最终得到以下结果:

            @Override
            public Class<?> getColumnClass(int columnIndex){
                if( columnIndex == 0){
                    // Return the column class for the integer column
                }else{
                    // Return the column class like we normally would have if we didn't override this method
                }

                return null;
            }
        };

我以前从未覆盖过它,我不太确定它希望我在这里做什么。

【问题讨论】:

  • 几乎总是建议覆盖 getColumnClass:不仅(可比较对象的)排序按预期完成,而且通常还处理编辑时的格式化渲染和类型转换。顺便说一句:永远不要从 getColumnClass 返回 null ...

标签: java swing sorting jtable


【解决方案1】:

试试这个小例子。

更好的方法

正如 Kleopatra 所建议的,为每个定义一个相关的列类就足以使数据正确排序。

import javax.swing.*;
import javax.swing.table.*;
import java.util.Comparator;

class TableSorting {
    public static void main(String[] args) {
        Object[][] data = {
            {new Integer(1), "Don't Let Go", new Integer(179)},
            {new Integer(2), "Photograph", new Integer(29)},
            {new Integer(3), "Hash Pipe", new Integer(186)},
            {new Integer(4), "Island In The Sun", new Integer(200)},
            {new Integer(5), "Crab", new Integer(154)},
            {new Integer(6), "Knock-Down Drag-Out", new Integer(128)},
            {new Integer(7), "Smile", new Integer(158)},
            {new Integer(8), "Simple Pages", new Integer(176)},
            {new Integer(9), "Glorious Day", new Integer(160)},
            {new Integer(10), "O Girlfriend", new Integer(230)}
        };
        Object[] columns = {"Track #", "Title", "Length"};
        DefaultTableModel model = new DefaultTableModel(data,columns) {
            @Override
            public Class getColumnClass(int column) {
                switch (column) {
                    case 0:
                        return Integer.class;
                    case 1:
                        return String.class;
                    case 2:
                        return Integer.class;
                    default:
                        return String.class;
                }
            }
        };
        JTable table = new JTable(model);
        JScrollPane scroll = new JScrollPane(table);
        table.setAutoCreateRowSorter(true);
        JOptionPane.showMessageDialog(null, scroll);
    }
}

原始,使用比较器

import javax.swing.*;
import javax.swing.table.*;
import java.util.Comparator;

class TableSorting {
    public static void main(String[] args) {
        Object[][] data = {
            {new Integer(1), "Don't Let Go", new Integer(179)},
            {new Integer(2), "Photograph", new Integer(29)},
            {new Integer(3), "Hash Pipe", new Integer(186)},
            {new Integer(4), "Island In The Sun", new Integer(200)},
            {new Integer(5), "Crab", new Integer(154)},
            {new Integer(6), "Knock-Down Drag-Out", new Integer(128)},
            {new Integer(7), "Smile", new Integer(158)},
            {new Integer(8), "Simple Pages", new Integer(176)},
            {new Integer(9), "Glorious Day", new Integer(160)},
            {new Integer(10), "O Girlfriend", new Integer(230)}
        };
        Object[] columns = {"Track #", "Title", "Length"};
        JTable table = new JTable(data, columns);
        JScrollPane scroll = new JScrollPane(table);
        DefaultTableModel model = new DefaultTableModel(data,columns);
        TableRowSorter trs = new TableRowSorter(model);

        class IntComparator implements Comparator {
            public int compare(Object o1, Object o2) {
                Integer int1 = (Integer)o1;
                Integer int2 = (Integer)o2;
                return int1.compareTo(int2);
            }

            public boolean equals(Object o2) {
                return this.equals(o2);
            }
        }

        trs.setComparator(0, new IntComparator());

        table.setRowSorter(trs);

        scroll = new JScrollPane(table);
        table.setAutoCreateRowSorter(false);
        JOptionPane.showMessageDialog(null, scroll);
    }
}

【讨论】:

  • 很高兴在示例中使用 optionPane 作为顶级容器 :-)
  • 是的,但是将 GUI 调用包装在 Runnable 中并稍后调用它可能会更好。我不确定我的辩护是“不包括电池”还是“(耸耸肩)我太懒了”。 ;)
  • 看过了,可以不提了,努力,呵呵
  • 最近,几乎我要找的每一个答案都被你优雅地回答了:)
  • @MarounMaroun 我认为这是吸引眼球的屏幕截图(偶尔也会投票)。有点像“去过那里,完成了 SSCCE,得到了屏幕截图”。 ;)
【解决方案2】:

好吧,DefaultTableModel 的文档确实说明了:

警告:DefaultTableModel 返回 Object 的列类。当 DefaultTableModel 与 TableRowSorter 一起使用时,这将导致 toString 的广泛使用,这对于非字符串数据类型来说是昂贵的。如果您将 DefaultTableModel 与 TableRowSorter 一起使用,强烈建议您重写 getColumnClass 以返回适当的类型。

所以听起来它只是将值转换为字符串,这与您所看到的一致。

您是否尝试过覆盖getColumnClass() 或调用setComparator() 以获得适当的TableRowSorter

【讨论】:

    【解决方案3】:

    答案如下: Problems with JTable sorting of integer values

    这个想法是为列定义类。

    myTable.setModel(new DefaultTableModel(Object[][] tableData, String[] columnsNames){
        Class[] types = { Boolean.class, Boolean.class, String.class, String.class };
    
        @Override
        public Class getColumnClass(int columnIndex) {
            return this.types[columnIndex];
        }
    });
    

    【讨论】:

      【解决方案4】:

      DefaultTableModel 返回 Object 的列类。因此,所有比较都将使用 toString 完成。这可能是不必要的昂贵。如果列仅包含一种类型的值,例如 Integer,则应覆盖 getColumnClass 并返回适当的 Class。这将显着提高此类的性能。

      在这种情况下,您应该在表模型中添加下面的 sn-p 代码:

          @Override
      public Class<?> getColumnClass(int columnIndex) {
          if (db.isEmpty()) {
              return Object.class;
          }
          return getValueAt(0, columnIndex).getClass();
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-28
        • 1970-01-01
        • 2019-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-12-05
        • 2023-03-08
        相关资源
        最近更新 更多