user2896152
user2896152

Reputation: 816

Sort JTable by value not included in the JTable

I've a JTable which shows an array of data of the type

String [] data = {"String1", "String2", "String3", "String4"};

but in the JTable I show only the first 3 items and the fourth is hidden for the user. But I would sorter the table even in base of the String4that is not shown in JTable. I read JTable tutorial and I found out how to use TableRowSorterand set a Comparator but method setComparator wants as its argument the column to order but this is not available for me.

Could anyone help me to solve this task? thank you

Upvotes: 3

Views: 363

Answers (1)

MadProgrammer
MadProgrammer

Reputation: 347204

The trick is, include the column in the TableModel, but remove it from the TableColumnModel

Sorted

The "A" column is actually randomly generated, so it will sort in an unpredictable manner

You can disable columns from been sortable using something like sorter.setSortable(1, false);, this could be used to prevent the user from clicking the column header and ruining your "hidden" sort.

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
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.TableRowSorter;

public class MagicSort {

    public static void main(String[] args) {
        new MagicSort();
    }

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

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private SortOrder order = SortOrder.ASCENDING;

        public TestPane() {
            RowDataTableModel model = new RowDataTableModel();
            TableRowSorter<RowDataTableModel> sorter = new TableRowSorter<>(model);
            sorter.setComparator(0, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return o1.compareTo(o2);
                }
            });

            JTable table = new JTable(model);
            table.setRowSorter(sorter);
            table.getColumnModel().removeColumn(table.getColumn("A"));

            setLayout(new BorderLayout());
            add(new JScrollPane(table));

            JButton change = new JButton("Change");
            add(change, BorderLayout.SOUTH);

            change.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    sort(sorter);
                }
            });

            sort(sorter);
        }

        protected void sort(TableRowSorter<RowDataTableModel> sorter) {

            List<RowSorter.SortKey> keys = new ArrayList<>(1);
            keys.add(new RowSorter.SortKey(0, order));

            sorter.setSortKeys(keys);

            switch (order) {
                case ASCENDING:
                    order = SortOrder.DESCENDING;
                    break;
                case DESCENDING:
                    order = SortOrder.UNSORTED;
                    break;
                case UNSORTED:
                    order = SortOrder.ASCENDING;
                    break;
            }

        }

    }

    public class RowDataTableModel extends AbstractTableModel {

        private List<RowData> data = new ArrayList<>(25);

        public RowDataTableModel() {
            for (int index = 0; index < 10; index++) {
                data.add(new RowData(index));
            }
        }

        public String getKeyColumnValue(int row) {
            return data.get(row).get(0);
        }

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

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

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return data.get(rowIndex).get(columnIndex);
        }

    }

    public class RowData {

        private List<String> values = new ArrayList<>();

        public RowData(int offset) {
            offset *= 5;
            for (int index = 1; index < 5; index++) {
                values.add(Character.toString((char) ('A' + (offset + index))));
            }

            values.add(0, Character.toString((char) ('A' + Math.random() * 26)));
        }

        public String get(int col) {
            return values.get(col);
        }

    }

}

Note: However, visually, this could be confusing to the user, so I'd use it sparingly.

Upvotes: 3

Related Questions