如果链接的模型元素具有ListProperty <>

时间:2018-12-21 23:50:45

标签: javafx-8 observable javabeans

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

number的类型为ObjectProperty,因为我也希望null成为可能的值,仅使用IntegerProperty是不可能的。像这样的Element类的size属性直接链接到数字列表的sizeProperty

numbersSize.bind(numbers.sizeProperty());

表和模型之间的连接是这样完成的

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

我计划在后台线程中对表元素进行一些时间密集的工作,在开始之前,我就测试过模型中的更改是否可以正确地反映在表中

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

现在发生的事情真是奇怪,我无法解决这个问题:

number列通过元素构造器显示的是1234而不是指定的0,到目前为止,对表所做的更改都很好。

numbers size列显示4个合适的位置,因为Element初始化时添加了1,2,3和9列表,到目前为止,对表所做的更改到目前为止都很好。

但是数字列表列仍显示[1,2,3],缺少9,为什么? TableColumn链接到ListProperty,并且ListProperty由包装在ObservableList中的ArrayList支持...,是否不应检测到对该列表的更改并将其传播回表?

如果我在表中添加了两个元素,并且还添加了删除Platform.runLater(...)中第二个元素的代码,则数字列将显示[1,2,3,9]。因此,问题似乎在于,number和numbersSize始终可以正确显示,但是列表号仅在从表视图后端添加/删除元素时才正确显示。

但是我想要的是tableview中的Elements数量根本不改变(一旦它最初被填充)。我想对每个元素的数字列表进行添加/删除,但这只是那些在更改时不会显示在UI中的元素:/

1 个答案:

答案 0 :(得分:0)

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