Иметь табличную модель. Необходимо сортировать по двум разным столбцам одновременно

Моя таблицаModel содержит несколько столбцов (например: столбцы A-F), из которых при первом отображении я должен отображать таблицу, отсортированную сначала по столбцу B, а затем по D. Теперь проблема, с которой я столкнулся, такова: столбец D метка времени. Колонка B содержит такие идентификаторы, как:

  1. (Цв. B) «Клт А - 001» (Цв. D) 11:34
  2. (Цв. B) «Клт B - 001» (Цв. D) 00:42
  3. (Цветок B) «Клт A - 001» (Цветок D) 13:18
  4. (Цв. B) «Клт. A - 002» (Цв. D) 13:18
  5. (Цв. B) «Клт C - 001» (Цв. D) 10:30
  6. (Цв. B) "Clt C - 001" (Цв. D) 14:45

Тип вывода, который мне нужен:

  1. (Цв. B) «Клт А - 001» (Цв. D) 11:34
  2. (Цветок B) «Клт A - 001» (Цветок D) 13:18
  3. (Цв. B) «Клт. A - 002» (Цв. D) 13:18
  4. (Цв. B) «Клт B - 001» (Цв. D) 00:42
  5. (Цв. B) «Клт C - 001» (Цв. D) 10:30
  6. (Цв. B) "Clt C - 001" (Цв. D) 14:45

Чего я не понимаю, так это того, что когда я пишу собственный метод compare(), я получаю только объект определенного столбца. Но если вы заметили в моем примере данных выше, сортировка зависит от информации во вторичном столбце. (Я не могу решить эту проблему с помощью sortPrecedence, потому что значение столбца B на самом деле не то же самое, когда метка времени в столбце D одинакова. Если я сначала отсортировал по столбцу D, а затем по столбцу B, то Порядок сортировки в первую очередь определяется временной меткой, а не алфавитным порядком столбца B. Является ли TableRowSorter моим вариантом? Если да, то как мне реализовать компаратор? Любая помощь с благодарностью.

Спасибо.


person user2406106    schedule 03.06.2013    source источник


Ответы (1)


Взгляните на Как использовать таблицы, Сортировка .

Есть пример, который демонстрирует, как настроить сортировку по нескольким столбцам...

Я цитирую...

Чтобы указать порядок сортировки и приоритет сортировки для столбцов, вызовите setSortKeys. Вот пример, который сортирует таблицу, используемую в примерах, по первым двум столбцам. Приоритет столбцов в сортировке определяется порядком ключей сортировки в списке ключей сортировки. В этом случае второй столбец имеет первый ключ сортировки, поэтому строки сортируются по имени, а затем по фамилии.

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);

Рабочий пример

введите здесь описание изображения

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;
        }
    }
}

Дополнительный

Просто укажите Comparator в требуемом столбце TableRowSorter, и вы сможете выполнить свои основные требования...

введите здесь описание изображения

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)));
    }
});

Вы должны иметь возможность указать сортировщик для каждого столбца, тем самым изменив способ сортировки под/групп...

person MadProgrammer    schedule 03.06.2013
comment
@camickr Я не могу вспомнить, кто указал мне на это, но я рад, что они это сделали :D - person MadProgrammer; 03.06.2013
comment
@MadProgrammer: я видел этот пример, который вы упомянули. Но в примере, который я упомянул, если была еще одна строка данных, например: (столбец B) Clt A - 002 (столбец D) 12:00 - и, скажем, я установил sortKeys и SortOrder, тогда будет новый строка, которую я только что упомянул, отображается как вторая строка в выходной таблице? Я спрашиваю, потому что я не могу попробовать это прямо сейчас, и мне нужно подождать до завтра, чтобы использовать систему, над которой я работаю для этого. Следовательно, я отмечу ответ как лучший, как только попробую. Спасибо. - person user2406106; 03.06.2013
comment
@MadProgrammer: вау, во-первых, похвала за ваши искренние усилия. Но, как я и ожидал, если вы заметите, что третья запись (Clt A - 002 @ 12:00 пополудни) ожидается (согласно моему требованию) как вторая запись. Потому что, хотя сортировка по столбцу B, она лишь частично отсортирована по этому Потому что мне нужно сортировать по Clt (A, B, C и т. д.), но независимо от того, является ли это заданием 001 или 002 этого clt, его нужно сортировать по времени. Даже если это один и тот же клиент ( с другим расширением, например 001/002), но с той же отметкой времени, он снова должен появиться в отсортированном порядке (Clt A -001 появляется перед Clt A - 002 с той же отметкой времени) - person user2406106; 03.06.2013
comment
возможно ли мне написать разные компараторы и сделать следующее: 1. сортировать по col.b (вызвать компаратор, который фильтрует, если это тот же клиент или нет) 2. если тот же клиент, сортировать по столбцу метки времени. 3. если одинаковая метка времени, сортировать по столбцу. снова b (но вызовите импл компаратора различий, который смотрит на вторую часть строки имени clt) - person user2406106; 03.06.2013
comment
Вы просмотрели JavaDocs? Вы можете указать компаратор для данного столбца - person MadProgrammer; 03.06.2013
comment
Завтра первым делом попробую. идея компаратора различий, реализуемого на одном и том же столбце, но на разных этапах сортировки, возникла только тогда, когда я писал ранее. Но спасибо, что попытались пройти через это со мной. Должен держать в курсе решения, когда я приземлюсь на него :) - person user2406106; 03.06.2013
comment
Я думаю, что это должно быть возможно с диетой по умолчанию, но вам может потребоваться вручную отсортировать модель заранее. - person MadProgrammer; 03.06.2013
comment
@MadProgrammer (пожалуйста, не воспринимайте как нападение) Мне нравятся ваши интересы, навыки ..., но это работает для меня без пользовательский компаратор, реализованный сортировщик быстрее, чем... (пожалуйста, может быть действительно беспорядок без оптимизаций, есть 2D-массив, а не сравнение, сортировка элементов в (J)List), извините, поместите туда 50 * 5k в JTable, а затем слушать через System.out.println - person mKorbel; 03.06.2013
comment
@MadProgrammer - Да, добавление компаратора действительно помогло! Большое спасибо, что остаётесь со мной на протяжении всего этого :) - person user2406106; 03.06.2013