20

I have a sortable JTable set up to use a custom extension of the AbstractTableModel. However, some behavior of this table is what I expected, and I would love some advice on how to figure this out.

I have the JTable set up to be sortable using:

thisJTable.setAutoCreateRowSorter(true);

This allows me to sort the table by clicking on the column headers as expected.

However, I find that when I sort the table by clicking on the column headers, the formatting (background and foreground color) of my rows are not sorted as well.

I had set up those rows to be color-coded based on the values they contain. When I sort by column header the formatting at a given row NUMBER stays the same (although the content that was previously in that row moved).

The color of the row is set by overriding the default prepareRenderer call for the JTable:

thisTable = new JTable(thisModel){

    //Set up custom rendering - Sets background color of row to correct value
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
        Component c = super.prepareRenderer(renderer, row, column);
        CustTableModel thisModel = (CustTableModel) getModel();
        c.setBackground(thisModel.getRowBackgroundColor(row));
        c.setForeground(thisModel.getRowForeColor(row));
        return c;
    }
};

Is there a better/different way to approach this?

Should I be using a different method to do my rendering, a method which would update the rendering of the JTable on a sort?

Or do I want to look into writing my own sorting method?

Solution (Thanks mKorbel!)

I thought I would post my solution, since I had to play with this a bit since I wasn't sure if the new index would be passed to the prepareRenderer as well.

 thisTable = new JTable(thisModel){

    //Set up custom rendering - Sets background color of row to correct value
    public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {

        int viewIdx = row;
        int modelIdx = convertRowIndexToModel(viewIdx);
        Component c = super.prepareRenderer(renderer, row, column);
        CustTableModel thisModel = (CustTableModel) getModel();
        c.setBackground(thisModel.getRowBackgroundColor(modelIdx));
        c.setForeground(thisModel.getRowForeColor(modelIdx));
        return c;
    }
};
Michael
  • 3,093
  • 7
  • 39
  • 83
Panky
  • 563
  • 1
  • 3
  • 18
  • I also may need to ensure that content-based formmatting is applied to rows after content is updated, but I haven't tackled that yet. I already am overwriting custTableModel.setValueAt(Object, int, int) so was thinking I had lots of options there, but thought I should mention that as well. – Panky Apr 25 '12 at 17:53
  • 1
    your prepareRenderer do nothing and complitating with CustTableModel thisModel = (CustTableModel) getModel();, remove that, [Renderer is only about formating, change Color, etc](http://stackoverflow.com/search?q=user%3A714968+prepareRenderer), not for create JComponent, don9t do that – mKorbel Apr 25 '12 at 18:46
  • @kKorbel I am not sure if I follow your comment. getRowForeColor and getRowBackgroundColor add conditional coloring for the row, based on the content of the row (hence passing rowIdx). I am using the super method to create the component and then simply setting the correct background and foreground color on that component. I need to get the TableModel and cast it to my CustTableModel because getRow[Fore|Background]Color is not a defined method for other table models. – Panky Apr 25 '12 at 19:55
  • iam curious about the detail of getRowBackgroundColor()); code inside ? @Panky – gumuruh Aug 28 '17 at 15:52

2 Answers2

19

you have to convert row index from View to the Model

int modelRow = convertRowIndexToModel(row);
Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • 2
    darn, you beat me (still fighting my new keyboard:-) +1, of course – kleopatra Apr 25 '12 at 17:56
  • Awesome! Thanks for the tip, I had been looking at the Javadoc for JTable for a while but didn't stumble upon this somehow. – Panky Apr 25 '12 at 18:11
  • 2
    @Panky: "When using a sorter, always remember to translate cell coordinates."—[Sorting and Filtering](http://docs.oracle.com/javase/tutorial/uiswing/components/table.html#sorting); sadly, I've had to look it up more than once. :-) – trashgod Apr 26 '12 at 02:30
6

You can enable table sorting by clicking on header using this table.setAutoCreateRowSorter(true);

for more information visit this site http://www.codejava.net/java-se/swing/6-techniques-for-sorting-jtable-you-should-know

Filip Kováč
  • 499
  • 8
  • 15
  • I can't believe that this answer is not the accepted answer. So elegant and simple. Thanks – Mijo Jul 09 '21 at 13:21