Как предотвратить TableView от переупорядочения TableColumn в javaFX 8?

Я прочитал это https://bugs.openjdk.java.net/browse/JDK-8102128 но я не нашел что-то в API JavaFX 8. Нет ли способа предотвратить переупорядочение в TableView?

9 ответов

Решение

Потратил пол дня, пытаясь решить проблему. Может быть, мое расследование может быть полезным для кого-то еще. Можно отключить переупорядочение столбцов с помощью некоторых хаков. И вот шаги:

  1. Получить заголовок таблицы. Это можно сделать, как описано здесь: /questions/24909799/kak-javafx-skryit-fonovyij-zagolovok-tablitsyi/24909808#24909808
  2. Добавьте прослушиватель события изменения в reorderingProperty, который устанавливает переупорядочение обратно в false.

Полный код здесь:

tableView.widthProperty().addListener(new ChangeListener<Number>()
{
    @Override
    public void changed(ObservableValue<? extends Number> source, Number oldWidth, Number newWidth)
    {
        TableHeaderRow header = (TableHeaderRow) tableView.lookup("TableHeaderRow");
        header.reorderingProperty().addListener(new ChangeListener<Boolean>() {
            @Override
            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                header.setReordering(false);
            }
        });
    }
});

Я не уверен в побочных эффектах этого решения, но быстрые тесты показывают, что решение работает хорошо.

Я знаю вопрос с тегом java-8 но для тех, кто бродит, Java 9 все вышеперечисленные коды сломались бы из-за модульности, которые делают .sun пакет недоступен и удаление impl_, Несмотря на эти изменения, он представляет удобные общедоступные методы, которые вы можете использовать:

  • setReorderable(boolean value)
  • getReorderable()

за TableColumnBase такие как TableColumn использоваться для набора Reorderable,

Мне нравится идея Александра Чингарева, но я думаю, что код вызовет утечки памяти! Каждый раз, когда свойство width изменяется, новый слушатель регистрируется, а старые слушатели никогда не собираются сборщиком мусора! Таким образом, вы можете либо сохранить ссылку на прослушиватель и убедиться, что удалили ее из наблюдаемого значения (в данном случае это свойство переупорядочения) перед добавлением нового прослушивателя, либо убедиться, что прослушиватель добавляется только один раз в свойство переупорядочения.

Я использовал свойство skin, которое изменяется только один раз (если я не ошибаюсь), чтобы добавить моего слушателя:

tableView.skinProperty().addListener((obs, oldSkin, newSkin) -> {
    final TableHeaderRow header = (TableHeaderRow) lookup("TableHeaderRow");
    header.reorderingProperty().addListener((o, oldVal, newVal) -> header.setReordering(false));
});

Альтернативное решение, которое не требует использования частного API в Java 8.

public static <T> void preventColumnReordering(TableView<T> tableView) {
    Platform.runLater(() -> {
        for (Node header : tableView.lookupAll(".column-header")) {
            header.addEventFilter(MouseEvent.MOUSE_DRAGGED, Event::consume);
        }
    });
}

API, добавленный в Java 8 RT-24669, является column.impl_setReorderable(false);,

Вы можете увидеть impl_setReorderable определение в источнике TableColumnBase.java.

Однако этот API предназначен только для внутреннего использования, помечен как устаревший и не является частью общедоступного API JavaFX.

В общем, impl_ методы в JavaFX будут удалены в будущем, что может повредить ваш код, если вы попытаетесь их использовать.

При рассмотрении кода для реализации переопределяемого свойства для столбцов таблицы он работает, игнорируя определенные события мыши, направленные на заголовок столбца таблицы. Найдите код TableColumnHeader.java для isReorderable для получения дополнительной информации.

Я не уверен, как бы вы сделали то же самое поведение, что и impl_setReorderable API использует только общедоступный API JavaFX, не выполняя довольно много работы.

Расширяя предыдущий вклад, я нашел это

tableView.getColumns().forEach(e -> e.setReorderable(false));

быть очень полезным в Java 13.

Для пользователя FXML это легко сделать, добавив reorderable="false"

<TableColumn fx:id="test" text="ColumnTitle" reorderable="false"/>

Спасибо! Он работает и с лямбдой, если у вас есть несколько таблиц, которые вы хотите отключить.

private void yourTableListeners(){
    yourTableView.widthProperty()
            .addListener((observable, oldValue, newValue) -> yourReusableDisablingMethod(yourTableView));
    anotherTableView.widthProperty()
            .addListener((observable, oldValue, newValue) -> yourReusableDisablingMethod(anotherTableView));
}

@SuppressWarnings("restriction")
private void yourReusableDisablingMethod(TableView tableView) {
    TableHeaderRow header = (TableHeaderRow) tableView.lookup("TableHeaderRow");
    header.reorderingProperty().addListener(new ChangeListener<Boolean>() {
        public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
            header.setReordering(false);
        }
    });
}

Если вам нужна сортировка по столбцам таблицы и переупорядочение вкладок, есть простое решение

      private void disableHeaderReorderingAndSorting() {
    tableView.skinProperty().addListener((a, b, newSkin) ->
    {
        Pane header = (Pane) tableView.lookup("TableHeaderRow");
        header.setMouseTransparent(true);
    });
}
Другие вопросы по тегам