4

Suppose I have a JTable with rows like this:

 (2, 1)
 (1, 3)
 (1, 5)
 (3, 1)
 (2, 3)
 (2, 4)

I want to sort JTable so that rows that have 1 in the first or second column are at the top, and the rest of the rows may have an arbitrary order:

 (1, 3)
 (1, 5)
 (2, 1)
 (3, 1)
 (2, 3)
 (2, 4)

Is there a way to do this in a table with TableRowSorter?

UPD: I want to sort the table programmatically, not through UI (clicking on the column headers)

lynxoid
  • 509
  • 6
  • 14

4 Answers4

1

You can define a Comparator for the first column using setComparator method. Then, in your compare method in the Comparator, return -1 if the first argument is 1, 1 if second argument is 1 and 0 otherwise.

Pulkit Goyal
  • 5,604
  • 1
  • 32
  • 50
  • I tried that -- this method would sort on the first column correctly, but if you use this same `Comparator` for the second column, it would produce something like: (1,3), (1,5), (2,1), (2, 3), (2, 4), (3,1) breaking up the 1's in the second column – lynxoid Mar 09 '12 at 16:25
1
  • not your are simply wrong, nor there reinvent the wheels by re_implementing one Comparator integrated in the API with another Comparator, another ways is implementing RowFilter, example for RowFilter

enter image description here

enter image description here

enter image description here

enter image description here

from code

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableBoolean extends JFrame {

    private final static String LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    private static final long serialVersionUID = 1L;
    private JTable table;
    private DefaultTableModel model;

    public TableBoolean() {
        Object[][] data = {{"A", new Boolean(false), 2, 1}, {"B", new Boolean(true), 1, 3},
            {"A", new Boolean(false), 1, 5}, {"B", new Boolean(true), 3, 1},
            {"A", new Boolean(false), 2, 3}, {"B", new Boolean(true), 2, 4},
            {"A", new Boolean(false), 5, 2}, {"B", new Boolean(true), 7, 1}};
        String[] columnNames = {"String", "Boolean", "Integer", "Integer"};
        model = new DefaultTableModel(data, columnNames) {

            private static final long serialVersionUID = 1L;

            @Override
            public Class getColumnClass(int column) {
                return getValueAt(0, column).getClass();
            }

            @Override
            public boolean isCellEditable(int row, int column) {
                return true;
            }
        };
        table = new JTable(model);
        TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel());
        table.setRowSorter(sorter);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        add(scrollPane);
        /*JButton button = new JButton("Add Row");
        button.addActionListener(new ActionListener() {

        @Override
        public void actionPerformed(ActionEvent e) {
        Object[] newRow = new Object[2];
        int row = table.getRowCount() + 1;
        newRow[0] = LETTERS.substring(row - 1, row);
        newRow[1] = (row % 2 == 0) ? new Boolean(true) : new Boolean(false);
        model.addRow(newRow);
        }
        });
        add(button, BorderLayout.SOUTH);*/
    }

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

            @Override
            public void run() {
                TableBoolean frame = new TableBoolean();
                frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
                frame.pack();
                frame.setVisible(true);
            }
        });
    }
}
Community
  • 1
  • 1
mKorbel
  • 109,525
  • 20
  • 134
  • 319
  • I don't want to filter out the rows - I want all rows to still be visible, but sorted in a way I described above. – lynxoid Mar 09 '12 at 16:57
  • @lynxoid you have to write own Comparator, with not aeasy & simple logics, have you got someone ???, – mKorbel Mar 09 '12 at 17:10
  • have look for SortKeys [here](http://stackoverflow.com/questions/6610291/sort-jtables-entries-without-clicking-on-column-header) or [here](http://stackoverflow.com/questions/4268124/jtable-and-sorting) – mKorbel Mar 09 '12 at 17:14
  • I do not see how SortKeys solves my original problem - unless you meant to apply them some very specific way – lynxoid Mar 09 '12 at 18:25
  • @lynxoid that reason why I answered ..., – mKorbel Mar 09 '12 at 18:30
1

I figured a way to do it w/o using TableRowSorter: you can presort data in the TableModel, then fire an event to let the table know that the data changed. Here is the pseudocode:

Set up the table:

AbstractTableModel model = new MyModel();
JTable table = new JTable(model);

Implement MyModel:

public class MyModel implements AbstractTableModel {
  private ArrayList<Integer> data;

  ...
  // implement interface methods
  ...

  public void sortToTop(int a) {
    // float all rows w/ a in the first column to the top
    Collections.sort(data, new Comparator<Integer>() {
        public int compare(int o1, int o2) {
            if (o1 == a) return -1;
            if (o2 == a) return 1;
            return o1.compareTo(o2);
        }
    });
    // find how many rows at the top have a in the first row
    int startIndex = 0;
    boolean notFound = true;
    while (startIndex < data.size() && notFound) {
        if (data.get(startIndex) == a)
            startIndex++;
        else 
            notFound = false;
    }
    int endIndex = data.size();
            // get a sublist w/o these first rows
    List<Integer> sublist = data.subList(startIndex, endIndex);
    // sort sublist on the second column floating a to the top
    Collections.sort(sublist, new Comparator<Integer>() {
        public int compare(int o1, int o2) {
            if (o1 == a) return -1;
            if (o2 == a) return 1;
            return o1.compareTo(o2);
        }
    });
    this.fireTableDataChanged();
  }
}
lynxoid
  • 509
  • 6
  • 14
0

The easiest way to do this in my opinion is to first call sort on the second column, which will result in something like this:

(3, 1)
(2, 1)
(1, 3)
(2, 3)
(2, 4)
(1, 5)

but this is not yet complete. If we then call sort on the first column, then we will have:

(1, 3)
(1, 5)
(2, 1)
(2, 3)
(2, 4)
(3, 1)

This is by far the easiest way to do it.

Aceman1987
  • 13
  • 5