gpt4 book ai didi

JavaFX:自定义等于方法导致 TableView 中没有刷新

转载 作者:行者123 更新时间:2023-12-02 03:17:58 42 4
gpt4 key购买 nike

情况如下:我有一个 ObservableSet(因为我的数据的 ID 字段必须是唯一的),它有一个监听器。该监听器更新 ObservableList。该 ObservableList 又由 TableView 监听。 (根据评论,这都是必要的,因为 ObservableSet 不能用于支持 JavaFX 中的 TableView。)

但是,我们发现,对 Set 执行多个 add 操作不会触发 TableView 的刷新。

这适用于:

  • 初始名单人口
  • 重复的设置条目(监听器不会被触发,这是预期的行为)

但是,编辑值时,TableView 仅在存在单个 add 语句时才会触发(在下面的示例中,注释掉 markStructure.add(new MarkStructureItem(2, 15)) ; 使它工作正常,但这样你就只有一个值)。如果有多个,TableView 不会刷新。

可以通过在 Listener 类末尾添加手动刷新 (tblTable.refresh()) 来解决此问题。这实际上是迄今为止它的运作方式,但现在的开发需要删除它。

知道发生了什么吗?为什么后续 add 没有触发 TableView 上的监听器?数据被放入集合和列表中,这已经确定了;它只是没有触发刷新。

代码示例(不是生产环境,而是我用来测试和获取答案的 POC):

public class TestController implements Initializable {
ObservableSet<MarkStructureItem> markStructure = FXCollections.observableSet();
ObservableList<MarkStructureItem> listMarkStructure = FXCollections.observableArrayList();

@FXML
private Pane root;

@FXML
private TableView<MarkStructureItem> tblTable;

@FXML
private TableColumn<MarkStructureItem, Integer> col1;

@FXML
private TableColumn<MarkStructureItem, Integer> col2;

@FXML
private Button btnButton;

private void resetAll() {
markStructure.clear();
markStructure.add(new MarkStructureItem(1, 25));
markStructure.add(new MarkStructureItem(2, 15));
}

@FXML
private void handleButtonAction(ActionEvent event) throws IOException {
Object source = event.getSource();
Button btnSource = (Button) source;
Stage stage = (Stage) root.getScene().getWindow();

switch (btnSource.getId()) {
case "btnButton": {
resetAll();
break;
}
}
}

class MarksUpdater<MarkStructureItem extends configurationeditor.MarkStructureItem> implements SetChangeListener {
@Override
public void onChanged(Change change) {
if (change.wasRemoved()) {
listMarkStructure.remove(change.getElementRemoved());
} else if (change.wasAdded()) {
MarkStructureItem newMarks = (MarkStructureItem) change.getElementAdded();
listMarkStructure.add(newMarks);
}
}
}

@Override
public void initialize(URL url, ResourceBundle rb) {
markStructure.addListener(new MarksUpdater<MarkStructureItem>());

col1.setCellValueFactory(
new PropertyValueFactory<MarkStructureItem, Integer>("id")
);
col2.setCellValueFactory(
new PropertyValueFactory<MarkStructureItem, Integer>("marks")
);
col2.setCellFactory(TextFieldTableCell.forTableColumn(new IntegerStringConverter()));
col2.setOnEditCommit(
new EventHandler<CellEditEvent<MarkStructureItem, Integer>>() {
@Override
public void handle(CellEditEvent<MarkStructureItem, Integer> t) {
((MarkStructureItem) t.getTableView().getItems().get(
t.getTablePosition().getRow())
).setMarks(t.getNewValue());
}
}
);
tblTable.setItems(listMarkStructure);

resetAll();
}
}

markStructure类:

public class MarkStructureItem {
final SimpleIntegerProperty marks;
final SimpleIntegerProperty id;

@Override
public int hashCode() {
return this.getId().hashCode();
}

@Override
public boolean equals(Object obj) {
if (obj.getClass() == this.getClass()) {
MarkStructureItem thisObj = (MarkStructureItem) obj;
return thisObj.getId() == this.getId();
}
return false;
}

public MarkStructureItem(Integer finishPosition, Integer marks) {
this.marks = new SimpleIntegerProperty(marks);
this.id = new SimpleIntegerProperty(finishPosition);
}

public Integer getId() {
return id.get();
}

public void setMarks(Integer value) {
marks.set(value);
}

public Integer getMarks() {
return marks.get();
}

public void setId(Integer value) {
id.set(value);
}
}

最佳答案

问题 1:

您的 equals 实现不是 null 安全的,并且您正在使用引用相等性来比较 Integer (==) 而不是 等于。只要您在缓存值的范围内并使用自动装箱,这可能就可以工作,但在该范围之外就不再工作(该范围仅保证为 -128 到 127,请参阅 Integer.valueOf(int) )。
由于您在 Set 中使用 Object,因此我建议无论如何都使 id 不可修改。否则,您需要先从集合中删除该值,然后再修改它并将其添加回Set(哈希码发生变化),这会打乱列表中的顺序,除非您暂时阻止 >SetChangeListener 更新列表。
使用原始类型还可以防止 == 出现问题。

问题 2:

要使 marks 属性中的任何更改在 TableView 中可见,您需要提供返回该属性的 marksProperty() 方法本身。这是 TableView 监听属性更改所必需的。

public class MarkStructureItem {

final SimpleIntegerProperty marks;
final int id;

@Override
public int hashCode() {
return id;
}

@Override
public boolean equals(Object obj) {
return obj != null
&& obj.getClass() == this.getClass()
&& this.id == ((MarkStructureItem) obj).id; // primitive type can be compared using ==
// && this.getId().equals(((MarkStructureItem) obj).getId()); // alternative for non-primitive types
}

public MarkStructureItem(int finishPosition, Integer marks) {
this.marks = new SimpleIntegerProperty(marks);
this.id = finishPosition;
}

public int getId() {
return id;
}

public IntegerProperty marksProperty() {
return marks;
}

关于JavaFX:自定义等于方法导致 TableView 中没有刷新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40032448/

42 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com