Javafx: повторная сортировка столбца в TableView

У меня есть TableView, связанный с TreeView. Каждый раз, когда узел в TreeView выбран, TableView обновляется с различными данными.

Я могу сортировать любой столбец в TableView, просто нажав на соответствующий заголовок столбца. Это прекрасно работает.

но: когда я выбираю другой узел в древовидном представлении, хотя заголовки столбцов продолжают отображаться как отсортированные. Данных нет.

есть ли способ программно применять порядок сортировки, выполняемый Пользователем при каждом изменении данных?

7 ответов


Ок, я нашел как это сделать. Я подытожу это здесь, если это полезно для других:

до вы обновляете содержимое TableView, вы должны сохранить sortcolum (если есть) и sortType:

        TableView rooms;
        ...
        TableColumn sortcolumn = null;
        SortType st = null;
        if (rooms.getSortOrder().size()>0) {
            sortcolumn = (TableColumn) rooms.getSortOrder().get(0);
            st = sortcolumn.getSortType();
        }

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

       if (sortcolumn!=null) {
            rooms.getSortOrder().add(sortcolumn);
            sortcolumn.setSortType(st);
            sortcolumn.setSortable(true); // This performs a sort
        }

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


У меня была такая же проблема, и я узнал, что после обновления данных вам нужно только вызвать функцию sort () на табличном представлении:

TableView rooms;
...
// Update data of rooms
...
rooms.sort()

таблица знает столбцы для сортировки таким образом, функция сортировки будет сортировать новые данные в нужном порядке. Эта функция доступна только в Java 8.


Если ваш TableView не повторно инициализирован, вы также можете сделать следующее:

TableColumn<BundleRow, ?> sortOrder = rooms.getSortOrder().get(0);
rooms.getSortOrder().clear();
rooms.getSortOrder().add(sortOrder);

пример fornacif работает, но не если есть более одного порядка сортировки (попробуйте Shift-клик на второй столбец, чтобы создать вторичный порядок сортировки).

чтобы выполнить повторную сортировку по всем столбцам, вам нужно будет сделать что-то вроде этого:

List<TableColumn<Room, ?>> sortOrder = new ArrayList<>(roomTable.getSortOrder());
roomTable.getSortOrder().clear();
roomTable.getSortOrder().addAll(sortOrder);

Если вы используете TableView.метод setItems (), похоже, сбрасывает несколько аспектов TableView. Оставьте ObservableList в TableView на месте, очистите его содержимое, а затем добавьте новые элементы. Затем TableView Для.sort () по-прежнему будет знать, какие столбцы были ранее отсортированы, и он будет работать. Вот так:

  tableView.getItems().clear();
  tableView.getItems().addAll(newTableData);
  tableView.sort();

ответ Марко Якоба хорош для большинства случаев, но я обнаружил, что мне нужно создать компаратор, который соответствует порядку сортировки таблицы для большей гибкости. Затем вы можете использовать любой метод, который использует компаратор для сортировки,поиска и т. д. Чтобы создать компаратор, я расширил это ComparatorChain класс из общих коллекций apache, чтобы легко выполнять сортировку нескольких столбцов. Похоже на то.

public class TableColumnListComparator extends ComparatorChain {
    public TableColumnListComparator(ObservableList<? extends TableColumn> columns) {
        // Get list of comparators from column list.
        for (TableColumn column : columns) {
            addComparator(new ColumnComparator(column));
        }
    }

    /**
     * Compares two items in a table column as if they were being sorted in the TableView.
     */
    private static class ColumnComparator implements Comparator {

        private final TableColumn column;

        /**
         * Default Constructor.  Creates comparator based off given table column sort order.
         *
         * @param column
         */
        public ColumnComparator(TableColumn column) {
            this.column = column;
        }

        @Override
        public int compare(Object o1, Object o2) {
            // Could not find a way to do this without casts unfortunately
            // Get the value of the column using the column's cell value factory.
            final ObservableValue<?> obj1 = (ObservableValue) column.getCellValueFactory().call(
                    new TableColumn.CellDataFeatures(column.getTableView(), column, o1));
            final ObservableValue<?> obj2 = (ObservableValue) column.getCellValueFactory().call(
                    new TableColumn.CellDataFeatures(column.getTableView(), column, o2));
            // Compare the column values using the column's given comparator.
            final int compare = column.getComparator().compare(obj1.getValue(), obj2.getValue());
            // Sort by proper ascending or descending.
            return column.getSortType() == TableColumn.SortType.ASCENDING ? compare : -compare;
        }
    }
}

вы можете сортировать в любое время с

Collections.sort(backingList, new TalbeColumnListComparator(table.getSortOrder());

Я использую это для сортировки нескольких списков с одной и той же сортировкой, сортировки в фоновых потоках, эффективных обновлений без использования всего списка и т. д. Я думаю, что будут некоторые улучшения сортировки таблиц в Javafx 8, поэтому это не будет необходимо в будущем.


вы также можете использовать SortedList.

SortedList<MatchTableBean> tableItems = new SortedList<>(
        observableList, Comparator.comparing(MatchTableBean::isMarker).reversed().thenComparing(MatchTableBean::getQueryRT));
    tableItems.comparatorProperty().bind(table.comparatorProperty());
    table.setItems(tableItems);

таким образом таблица сортируется, даже если содержимое изменяется или полностью заменяется.