我的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中的元素:/
答案 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<>());