Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does my JTable sort an integer column incorrectly?

I have a JTable that uses a DefaultTableModel and I allow for sorting when the user clicks on the column headers. However, when the user clicks on a header for a column that has data of type integer it does not sort properly. It seems like it is sorting by String instead of an integer type.

Here is the part of my code where I actually add the data to the table:

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

So I tried to override that method and ended up with this:

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

I've never overridden this before and I'm not quite sure what it is expecting me to do here.

like image 566
Brian T Hannan Avatar asked Jul 06 '11 06:07

Brian T Hannan


3 Answers

Try this little example.

Sorted 1st column

The better way

As suggested by Kleopatra, defining a column class relevant for each, will be enough to get the data to be sorted correctly.

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

Original, using a comparator

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);
    }
}
like image 65
Andrew Thompson Avatar answered Sep 19 '22 19:09

Andrew Thompson


Well, the docs for DefaultTableModel do state:

Warning: DefaultTableModel returns a column class of Object. When DefaultTableModel is used with a TableRowSorter this will result in extensive use of toString, which for non-String data types is expensive. If you use DefaultTableModel with a TableRowSorter you are strongly encouraged to override getColumnClass to return the appropriate type.

So it sounds like it's just going to be converting values to strings, which would be consistent with what you're seeing.

Have you tried either overriding getColumnClass() or calling setComparator() for the appropriate TableRowSorter?

like image 43
Jon Skeet Avatar answered Sep 20 '22 19:09

Jon Skeet


Here is the answer: Problems with JTable sorting of integer values

The idea is to define classes for columns.

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];
    }
});
like image 33
Zakhar Avatar answered Sep 22 '22 19:09

Zakhar