Sorting double values in JTable
Asked Answered
H

2

6

I have found quite a few questions related to this but I haven't found a simple solution to my issue though.

I can't find a way to make my JTable sort Double values properly.

I extended AbstractTableModel to receive a Class array and return the proper types per column:

class TableModelMod extends AbstractTableModel{

    private ArrayList data;
    private String [] headers;
    private Class [] types;

    TableModelMod(String [] heads, ArrayList datas, Class [] classes){
        headers = heads;
        data = datas;
        types = classes;
    }
    ... 
    @Override public Class getColumnClass(int c){
        if (c > types.length - 1)
            return null;
        else 
            return types[c];
    }
...

And then in my custom JTable constructor:

TableRowSorter<TableModelMod> sorter = new TableRowSorter<TableModelMod>((TableModelMod)getModel());

But then I get this error when adding rows:

java.lang.IllegalArgumentException: Cannot format given Object as a Number

It fails at method DecimalFormat.format(Object number, StringBuffer toAppendTo, FieldPosition pos) that accepts most numeric types but Double.

If I use another class for the Double columns I get no error but still the sorting does not work as expected. I tried with different numeric classes but none seem to sort doubles correctly:

@Override public Class getColumnClass(int c){
    if (c > types.length - 1)
        return null;
    else if (types[c] == Double.class)
        return Number.class;
    else 
        return types[c];
}

I'm not sure if I what I need is to implement a custom RowSorter, a custom CellRenderer, or both.

Could someone guide me on how to fix this the simpler way?

Thanks a lot and best regards.

EDITED: SOLVED

It's quite embarrassing to tell where the problem was.

The ArrayList containing the Object[] rows was filled from a database ResultSet using getString(int) instead of getObject(int) or getDouble(int), therefore the value could not be used as Double by the renderer. It's weird that it didn't give exceptions using Integer or Number as column class, but it was being sorted as a String anyways. I was looking for an issue in the wrong classes since I was convinced my ArrayList contained just Objects.

Thanks a lot for your examples, looking at them I noticed my doubles were actually Strings and then I could find where the conversion was happening.

Hixson answered 4/9, 2011 at 12:42 Comment(1)
You should remove the solution from your question and add it as an answer.Hsinking
P
6

Check out this code. It sorts double values.

enter image description here

enter image description here

import java.awt.BorderLayout;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;

public class RowSorterDemo {
  public static void main(String args[]) {
    JFrame frame = new JFrame("Sort Table Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Object rows[][] = { { "J", 23.1 }, { "R", 21.1, }, { "E", 21.2, }, { "B", 27.1, }, { "A", 25.2, },
        { "S", 22.9, }, };

    String columns[] = { "Name", "Age" };

    TableModel model = new DefaultTableModel(rows, columns) {
      public Class getColumnClass(int column) {
        Class returnValue;
        if ((column >= 0) && (column < getColumnCount())) {
          returnValue = getValueAt(0, column).getClass();
        } else {
          returnValue = Object.class;
        }
        return returnValue;
      }
    };

    JTable table = new JTable(model);

    RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(model);

    table.setRowSorter(sorter);

    JScrollPane pane = new JScrollPane(table);

    frame.add(pane, BorderLayout.CENTER);

    frame.setSize(300, 150);
    frame.setVisible(true);
  }
}

I modified the source given at this link a little bit so that it takes double values.

Pyrex answered 4/9, 2011 at 13:6 Comment(3)
Does this still work if you don't explicitly set the RowSorter? I have never had to manually set a sorter and sorting still works as long as getColumnClass() returns the correct class.Allegorical
If I don't set explicitly the RowSorter nothing happens when I click on a header.Hixson
you don't have to set the sorter explicitly, simply enable sorting by table.setAutoCreateRowSorter(true)Electrolyze
K
6

this code could be your SSCCE, can you demonstate you issue on this code, nothing from code snipped that you posted

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

public class TableTest2 {

    public void initGUI() {
        String[] columnNames = {"numbers","double", "text"};
        Object[][] data = {{1, 0.81, "A"}, {10, 5.268752005, "B"}, {7, 100.0,"C"},{6, 52.879999, "A"},
        {4, 62.50, "B"}, {2, 854.9999, "C"},{11, 19.01, "A"}, {100, 0.0009, "B"}, {20, 100.09, "C"}};
        JTable table = new JTable(new DefaultTableModel(data, columnNames) {

            private static final long serialVersionUID = 1L;

            @Override
            public java.lang.Class<?> getColumnClass(int c) {
                return getValueAt(0, c).getClass();
            }
        });
        table.setAutoCreateRowSorter(true);
        table.getRowSorter().setSortKeys(Arrays.asList(new RowSorter.SortKey(0, SortOrder.ASCENDING)));
        JFrame frame = new JFrame("LFIXimate");
        frame.setResizable(true);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.add(new JScrollPane(table));
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new TableTest2().initGUI();
            }
        });
    }
}
Kirkcudbright answered 4/9, 2011 at 13:13 Comment(3)
Thanks a lot for your code I tested both before I found my mistake, it's just Bragboy's looked a bit clearer, but really, thank you very much =)Hixson
@Kirkcudbright +1 Nice answer. Hi back. Nice to see you to mate. I am rarely active these days. Too busy with other stuff :)Clip
+1 examples getting shorter - gooood :-) No need for SortKeys, though: getRowSorter().toggleSortOrder(0) will do the initial sortingElectrolyze

© 2022 - 2024 — McMap. All rights reserved.