-1

In fact, it's more an answer than a question. I have had an issue with TableRowSorter when creating JTable from file. I use TableModel like this:

public class TModel extends AbstractTableModel {

    public Vector data;
    public Vector colNames;
    public String datafile;
    Class[] types = {Integer.class, Date.class, Number.class, String.class, Character.class};

    public TModel(String f) {
        datafile = f;
        initVectors();
    }

    public void initVectors() {
        String aLine;
        data = new Vector();
        colNames = new Vector();
        try {
            FileInputStream fin = new FileInputStream(datafile);
            BufferedReader br = new BufferedReader(new InputStreamReader(fin));
            // extract column names
            StringTokenizer st1 =
                    new StringTokenizer(br.readLine(), "|");
            while (st1.hasMoreTokens())
                colNames.addElement(st1.nextToken());
            // extract data
            while ((aLine = br.readLine()) != null) {
                StringTokenizer st2 =
                        new StringTokenizer(aLine, "|");
                while (st2.hasMoreTokens())
                    data.addElement(st2.nextToken());
            }
            br.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int getRowCount() {
        return data.size() / getColumnCount();
    }

    public int getColumnCount() {
        return colNames.size();
    }

    public String getColumnName(int columnIndex) {
        String colName = "";

        if (columnIndex <= getColumnCount())
            colName = (String) colNames.elementAt(columnIndex);

        return colName;
    }

    public Class getColumnClass(int columnIndex) {
        return this.types[columnIndex];
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        return data.elementAt((rowIndex * getColumnCount()) + columnIndex);
    }

    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        return;
    }

The issue was that first column in table sorted like String regardless which type it returns from "GetColumnClass" method. Most popular recommendations for such problem are: "You should override your GetColumnClass method" or "Set specific type for each column".. Sadly, none of that works for me :_( This topic helped me a lot, mostly snippet from Alanmars. Simple soution: if TableRowSorter treats numbers like String, just make it compare them like Integer! Below - snippet, that works for me:

TModel tModel = new TModel(selectedFile);
JTable table = new JTable();
JScrollPane scrollPane = new JScrollPane(table, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
sorter = new TableRowSorter<>(tModel);
sorter.setComparator(IndexOfDesiredColumn, new Comparator<String>() {
    @Override
    public int compare(String n1, String n2) {
    return Integer.parseInt(n1) - Integer.parseInt(n2);
    }
});
table.setModel(tModel);
table.setRowSorter(sorter);

Hope this tread will save time for those who'll face same problem as me.

  • 1
    (1-) `The issue was that first column in table sorted like String regardless which type it returns from "GetColumnClass" method.` - then you have a problem with your code. Your workaround is unnecessary. Fix your code. Of course if you override the getColumnClass(...) method to return Integer, then you must also store Integer values in the model. The table will not convert the String to an Integer for you. – camickr Aug 15 '17 at 14:31
  • TY for comment, @camickr , but I only willing to share code snippet, that works in my case (that is why TModel class code is listed in post - to show complete picture). It's not the point for now if code seemed wrong or raw - it's working! And that is the point. I didn't ask anything, but thank you for sharing your knowlege.) – Raman Kryvasheyeu Aug 16 '17 at 10:05
  • `...it's working! And that is the point.` - that is the wrong point. The forum is used to promote good coding techniques. Your solution is a workaround because you don't understand how the JTable works. My comment was made so that others don't blindly follow the solution. – camickr Aug 16 '17 at 15:22
  • @camickr, I'm not going to disagree with you - good coding is always preferable. – Raman Kryvasheyeu Aug 17 '17 at 07:22

1 Answers1

-2

All of your columns get data from a raw Vector that is all those data are in Object...

And the sorter takes any Objects, that are not null, and calls toString() on them, and does the sorting with the result...

Your getColumnClass() method is not implemented right, as if there are no data in the model (EG it is empty) it will throw NullPointerException...

Usagi Miyamoto
  • 6,196
  • 1
  • 19
  • 33
  • 1
    (1-) `And the sorter takes any Objects, that are not null, and calls toString() on them, and does the sorting with the result...` - It doesn't call toString(). It just invokes the Comparator and passes the Object. The Comparator then does the comparison. – camickr Aug 15 '17 at 14:41
  • Take a look at the docs: http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting There is a 5 point list of steps, and the last one is `toString()`... – Usagi Miyamoto Aug 15 '17 at 14:43
  • Your answer implies that it is the first step. In any case this is at best a comment not a solution. It doesn't suggest how the getColumnClass() method should be implemented. Nor does it mention that the data in the model must also match the Class returned from that method. So in the OP's example you can't just override getColumnClass() to return Integer and then store a String object in the model. You must also store an Integer object in the model as I suggested in my original comment. – camickr Aug 15 '17 at 15:02