Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

My tableModel contains multiple columns (for ex: Columns A - F), of which when I first display, I should display the table sorted by firstly Column B and later by D. Now, the issue that am facing is: Col. D is timestamp. Col. B contains identifiers such as :

  1. (Col. B) "Clt A - 001" (Col. D) 11:34 AM
  2. (Col. B) "Clt B - 001" (Col. D) 12:42 AM
  3. (Col. B) "Clt A - 001" (Col. D) 1:18 PM
  4. (Col. B) "Clt A - 002" (Col. D) 1:18PM
  5. (Col. B) "Clt C - 001" (Col. D) 10:30 AM
  6. (Col. B) "Clt C - 001" (Col. D) 2:45 PM

The kind of output I need is:

  1. (Col. B) "Clt A - 001" (Col. D) 11:34 AM
  2. (Col. B) "Clt A - 001" (Col. D) 1:18 PM
  3. (Col. B) "Clt A - 002" (Col. D) 1:18PM
  4. (Col. B) "Clt B - 001" (Col. D) 12:42 AM
  5. (Col. B) "Clt C - 001" (Col. D) 10:30 AM
  6. (Col. B) "Clt C - 001" (Col. D) 2:45 PM

What I don't understand is, when I write a custom compare() method, I am only getting the object of a particular column. But if you observe in my sample data above, the sort depends on the information in teh secondary column. (Am not able to overcome this issue by using sortPrecedence because the value of Col. B is not actually same when the timestamp in col. D is the same. If I sorted initially by Col. D, and later by Col. B then the sort order is primarily driven by timestamp rather than by alphabetical order of Col. B. Is TableRowSorter my option? If so, how should I implement the comparator? Any help greatly appreciated.

Thanks.

share|improve this question

1 Answer 1

up vote 2 down vote accepted

Take a look at How to use tables, Sorting.

There is an example which demonstrates how to setup multi-column sorting...

I quote...

To specify the sort order and sort precedence for columns, invoke setSortKeys. Here is an example that sorts the table used in the examples by the first two columns. The precedence of the columns in the sort is indicated by the order of the sort keys in the sort key list. In this case, the second column has the first sort key, so they rows are sorted by first name, then last name.

List <RowSorter.SortKey> sortKeys 
    = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
sorter.setSortKeys(sortKeys);

Working Example

enter image description here

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.EventQueue;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.RowSorter;
import javax.swing.SortOrder;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableRowSorter;

public class TestMuiltColumnTableSort {

    public static void main(String[] args) {
        new TestMuiltColumnTableSort();
    }
    public static final SimpleDateFormat SDF = new SimpleDateFormat("hh:mm aa");

    public TestMuiltColumnTableSort() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                try {
                    MyTableModel model = new MyTableModel();
                    model.addRow("Job #1.1", "Clt A - 001", "11:34 AM");
                    model.addRow("Job #2.1", "Clt B - 001", "12:42 AM");
                    model.addRow("Job #1.1", "Clt A - 001", "01:18 PM");
                    model.addRow("Job #1.2", "Clt A - 002", "01:18 PM");
                    model.addRow("Job #3.1", "Clt C - 001", "10:30 AM");
                    model.addRow("Job #3.1", "Clt C - 001", "02:45 PM");
                    model.addRow("Job #1.2", "Clt A - 002", "12:00 PM");
                    JTable table = new JTable(model);
                    table.setAutoCreateRowSorter(false);
                    table.setDefaultRenderer(Date.class, new TimeCellRenderer());

                    TableRowSorter<MyTableModel> sorter = new TableRowSorter<MyTableModel>(model);
                    table.setRowSorter(sorter);

                    List<RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>();
                    sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
                    sortKeys.add(new RowSorter.SortKey(2, SortOrder.ASCENDING));
                    sorter.setSortKeys(sortKeys);

                    JFrame frame = new JFrame("Testing");
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.setLayout(new BorderLayout());
                    frame.add(new JScrollPane(table));
                    frame.pack();
                    frame.setLocationRelativeTo(null);
                    frame.setVisible(true);
                } catch (ParseException exp) {
                    exp.printStackTrace();
                    System.exit(0);
                }
            }
        });
    }

    public class TimeCellRenderer extends DefaultTableCellRenderer {

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); //To change body of generated methods, choose Tools | Templates.
            if (value instanceof Date) {
                setText(SDF.format(value));
            }
            return this;
        }
    }

    public class MyTableModel extends AbstractTableModel {

        private List<Row> rows = new ArrayList<>(25);

        public void addRow(String name, String cat, String date) throws ParseException {

            rows.add(new Row(name, cat, SDF.parse(date)));

        }

        @Override
        public int getRowCount() {
            return rows.size();
        }

        @Override
        public int getColumnCount() {
            return 3;
        }

        @Override
        public Class<?> getColumnClass(int columnIndex) {
            Class clazz = String.class;
            switch (columnIndex) {
                case 2:
                    clazz = Date.class;
                    break;
            }
            return clazz;
        }

        @Override
        public String getColumnName(int column) {
            String name = "??";
            switch (column) {
                case 0:
                    name = "Name";
                    break;
                case 1:
                    name = "Catagory";
                    break;
                case 2:
                    name = "Date";
                    break;
            }
            return name;
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            Row row = rows.get(rowIndex);
            Object value = null;
            switch (columnIndex) {
                case 0:
                    value = row.getName();
                    break;
                case 1:
                    value = row.getCat();
                    break;
                case 2:
                    value = row.getDate();
                    break;
            }
            return value;
        }
    }

    public class Row {

        private String name;
        private String cat;
        private Date date;

        public Row(String name, String cat, Date date) {
            this.name = name;
            this.cat = cat;
            this.date = date;
        }

        public String getName() {
            return name;
        }

        public String getCat() {
            return cat;
        }

        public Date getDate() {
            return date;
        }
    }
}

Additional

Simply be providing a Comparator to the required column of the TableRowSorter you should be able to achieve your basic requirements...

enter image description here

sorter.setComparator(1, new Comparator<String>() {
    @Override
    public int compare(String o1, String o2) {
        return o1.substring(0, Math.min(o1.length(), 5)).compareTo(o2.substring(0, Math.min(o2.length(), 5)));
    }
});

You should be able to supply a camparator for each column, thus modifying how the sub/group sorting works...

share|improve this answer
    
+1, I didn't realize the tutorial had a example. –  camickr Jun 3 '13 at 2:37
    
@camickr I can't remember who pointed it out to me, but I'm glad they did :D –  MadProgrammer Jun 3 '13 at 2:38
    
@MadProgrammer: I had seen this example you mentioned. But in the example I mentioned, if there was another row of data as: (Col. B) "Clt A - 002" (Col. D) 12:00 PM - and let's say I set the sortKeys and the SortOrder, then will the new row that I just mentioned appear as the second row in the output table? Am asking coz I can't try it right away and need to wait till tomorrow to use the system am working on for this. Hence, will mark teh answer as "worked best" once I give it a shot. Thanks. –  user2406106 Jun 3 '13 at 2:47
    
@user2406106 I don't see the problem. I've added a working example... –  MadProgrammer Jun 3 '13 at 3:18
    
@MadProgrammer: wow, firstly accolades to your sincere effort. But, just as I had expected, if you notice the third record (Clt A - 002 @ 12:00pM is (per my requirement) expected as second record. Because, although sorting by Col. B, it sonly partially sorted by that, Coz I need to sort by the the Clt (A, B, C, etc)., but irresp of whether it is 001 job or 002 of that clt, it shud be sorted by time. In the even that its the same client (different extension such as 001/002) but same time stamp, it shud again appear in sorted order (Clt A -001 appears before Clt A - 002 of the same time stamp) –  user2406106 Jun 3 '13 at 5:17

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.