Как обновить TableView, если элементы связанной модели имеют ListProperty <> - PullRequest
0 голосов
/ 22 декабря 2018

My TableView содержит элементы, которые имеют несколько атрибутов, которые предоставляются с помощью свойств.Элемент состоит из списка чисел, называемых числами, размера этого списка, называемого numbersSize, и одного числа, называемого просто цифрой.Проблемным, который не будет обновляться в пользовательском интерфейсе, является список номеров.

Таблица и столбцы определены следующим образом:

@FXML private TableView<Element> table;
@FXML private TableColumn<Element, Integer> numberCol;
@FXML private TableColumn<Element, Integer> numbersSizeCol;
@FXML private TableColumn<Element, List<Integer>> numbersCol;

Класс элемента выглядит следующим образом

private ObjectProperty<Integer> number;
private IntegerProperty numbersSize;
private ListProperty<Integer> numbers;

public ObjectProperty<Integer> numberProperty() { return number;    } 
public IntegerProperty numbersSizeProperty() { return numbersSize; }    
public ListProperty<Integer> numbersProperty() { return numbers; }

число имеет тип ObjectProperty, потому что я хочу, чтобы значение NULL также было возможным, что невозможно при использовании только IntegerProperty.Свойство size класса Element напрямую связано с sizeProperty списка чисел следующим образом

numbersSize.bind(numbers.sizeProperty());

Соединение между таблицей и моделью выполняется следующим образом:

numberCol.setCellValueFactory(new PropertyValueFactory<>("number"));
numbersSizeCol.setCellValueFactory(new PropertyValueFactory<>("numbersSize"));
numbersCol.setCellValueFactory(new PropertyValueFactory<>("numbers"));

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

List<Integer> l = new ArrayList<>();
l.add(1);
l.add(2);
l.add(3);
ObservableList<Integer> o = FXCollections.observableList(l);
Element e = new Element(0, o);
elementController.getElementList().add(e);

startBtn.setOnAction(e -> {         
        new Thread(() ->  {
            Element e = elementController.getElementList().get(0);
            Platform.runLater(() -> {
                e.numberProperty().set(1234);
                e.numbersProperty().add(9);
            });
        }).start();         
    });

ДействительноСтранная вещь, которая происходит сейчас и которую я не могу обернуть вокруг себя, заключается в следующем:

В столбце чисел показано 1234 вместо указанного 0 через конструктор элемента, пока что это хорошо, что изменение переносится втаблица.

В столбце размера чисел показано число 4, которое подходит, поскольку элемент был инициализирован с добавлением списка 1,2,3 и 9, что пока хорошо, что изменение перенесено в таблицу.

НО в столбце списка номеров все еще отображается [1,2,3], 9 отсутствует, почему это так?TableColumn связан с ListProperty, а ListProperty поддерживается ArrayList, обернутым в ObservableList ..., не должно ли изменение этого списка быть обнаружено и распространено обратно в таблицу?

Если я добавлю дваЭлементы к таблице, а также добавить код для удаления второго элемента в Platform.runLater (...), после чего отображается столбец чисел [1,2,3,9].Таким образом, проблема заключается в том, что number и numbersSize всегда отображаются правильно, но номера списков отображаются правильно только при добавлении / удалении элемента из бэкэнда просмотра таблицы.

Однако мне нужно количество элементов втабличное представление не изменяется вообще (как только оно изначально заполнено).Я хочу сделать добавления / удаления в список номеров каждого элемента, но это только те, которые не будут отображаться в пользовательском интерфейсе при изменении: /

1 Ответ

0 голосов
/ 22 декабря 2018

ListProperty<Integer> является Property<ObservableList<Integer>> и реализует ObservableList<Integer>.Изменения самого свойства применяются к значению, сохраненному в свойстве.

Это означает, что

e.numbersProperty().add(9);

имеет тот же эффект, что и

e.numbersProperty().get().add(9);

Эта операция незамените значение свойства, и поэтому TableCell не будет обновлено.

Чтобы обновить TableCell, даже если обновлен список в свойстве, вы можете реализовать пользовательский cellFactory:

public class ObservableItemTableCell<S, T extends Observable> extends TableCell<S, T> {
    final InvalidationListener l = o -> setText(getItem().toString());
    final WeakInvalidationListener listener = new WeakInvalidationListener(l);

    @Override
    protected void updateItem(T item, boolean empty) {
        // remove old listener
        T oldItem = getItem();
        if (oldItem != null) {
            oldItem.removeListener(listener);
        }

        super.updateItem(item, empty);

        if (empty || item == null) {
            setText("");
        } else {
            setText(item.toString());
            item.addListener(listener);
        }
    }
}
@FXML private TableColumn<Element, ObservableList<Integer>> numbersCol;
numbersCol.setCellValueFactory(new PropertyValueFactory<>("numbers"));
numbersCol.setCellFactory(col -> new ObservableItemTableCell<>());
...