views:

517

answers:

3

I am using JTable with an empty row at the bottom of the table in order to give the ability of adding new line to the table.

After insert or writing data in the empty row i am adding automtacly a new empty row below it. (It suppose to act like the Microsoft visual tables)

I am using the java default row sorter,

The problem is that i need the empty row to be the last row all the time! but after sorting the table it become the first row.

The "compare(int model1, int model2)" method of the DefaultRowSorter class is getting 2 row numbers and return -1 if the value of the first row is null and 1 if the value of the second row is null. and incase of DESCENDING it mult by -1 to get the inverted order.

            //Treat nulls as < then non-null
            if (v1 == null) {
                if (v2 == null) {
                    result = 0;
                } else {
                    result = -1;
                }
            } else if (v2 == null) {
                result = 1;
            } else {
                result = sortComparators[counter].compare(v1, v2);
            }
            if (sortOrder == SortOrder.DESCENDING) {
                result *= -1;
            }

The empty line is sorted as the smallest value and incase of DESCENDING it will be the first line (because of the mult by -1) and causes alot of problems.

I could overide it and incase of the empty row(usualy the last row) do not mult by -1 in DESCENDING mode, and it will be the last row after any sorting. But the problem is that the "compare" method and it's caller "Row" inner class are private inside the DefaultRowSorter.

Is there a way to avoid sorting the empty row and make it always the last row?

A: 

Set a different comparator using DefaultRowSorter's setComparator method.

Suraj Chandran
The handling of null values is done before invoking the custom comparator. (as the question also states)
Fedearne
+1  A: 

The DefaultRowSorter is definitely flawed.

The only option is to create your own RowSorter based on the DefaultRowsorter and correct the problem.

Se these forum posts.

http://forums.sun.com/thread.jspa?threadID=5406878&amp;tstart=0

http://forums.sun.com/thread.jspa?threadID=5210676&amp;tstart=-1

Fedearne
This solution is well known, but i want to know if there is a better solution that not includes copy an rewrite the DefaultRowSorter.
Billbo bug
I agree that is an annoying solution.
Fedearne
A: 

I gave this a try, and I think I found a solution.

Instead of creating that empty row in the TableModel, I fake it in the JTable, and only create it when the user actually enters some data.

The RowSorter only sorts rows of the TableModel, so our row is not affected and remains as the last row.

public class NewLineTable extends JTable {

    @Override
    public int getRowCount() {
        // fake an additional row
        return super.getRowCount() + 1;
    }

    @Override
    public Object getValueAt(int row, int column) {
        if(row < super.getRowCount()) {
            return super.getValueAt(row, column);
        }
        return ""; // value to display in new line
    }

    @Override
    public int convertRowIndexToModel(int viewRowIndex) {
        if(viewRowIndex < super.getRowCount()) {
            return super.convertRowIndexToModel(viewRowIndex);
        }
        return super.getRowCount(); // can't convert our faked row
    }

    @Override
    public void setValueAt(Object aValue, int row, int column) {
        if(row < super.getRowCount()) {
            super.setValueAt(aValue, row, column);
        }
        else {
            Object[] rowData = new Object[getColumnCount()];
            Arrays.fill(rowData, "");
            rowData[convertColumnIndexToModel(column)] = aValue;
            // That's where we insert the new row.
            // Change this to work with your model.
            ((DefaultTableModel)getModel()).addRow(rowData);
        }
    }
}
Peter Lang