当前位置: 首页 > 知识库问答 >
问题:

javafx:Custom Equals方法不会导致TableView中的刷新

赫连实
2023-03-14

情况是这样的:我有一个ObservableSet(因为我的数据的ID字段必须是唯一的),它有一个侦听器。该侦听器更新ObservableList。ObservableList反过来由TableView监听。(根据注释,这都是必要的,因为在JavaFX中不能使用ObservableSet支持TableView。)

然而,我们发现对集合执行多个add操作不会触发TableView的刷新。

    null

但是,编辑该值时,TableView只有在有一个add语句时才会触发(在下面的示例中,注释掉MarkStructure.add(new MarkStructureItem(2,15));使其工作良好,但只有一个值)。如果有多个,则TableView不会刷新。

这可以通过在侦听器类(tbltable.refresh())末尾添加手动刷新来解决。这实际上是它到现在为止的运作方式,但是现在的开发需要去掉它。

知道怎么回事吗?为什么TableView上的侦听器没有为后续的add触发?数据正在被放入集合和列表中,大部分已经确定;只是没有触发刷新。

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个答案

党宇定
2023-03-14

问题1:

您的equals实现不是null安全的,您使用引用相等(==)而不是equals来比较integer。只要您在缓存值的范围内并使用自动装箱,这可能就会起作用,但在该范围外就会停止工作(此范围只保证为-128到127,请参阅integer.valueof(int))。
由于您正在中使用对象,所以我建议您无论如何都不能修改ID。否则,您需要在修改该值并将其添加回(哈希代码更改)之前将其从集合中删除,这将扰乱列表中的顺序,除非您暂时阻止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;
    }
 类似资料:
  • 我有一个Angular的表单,里面有两个按钮标签。一个按钮提交上的表单。另一个按钮是纯导航使用。然而,当点击第二个按钮时,AngularJS会导致页面刷新,从而触发404。我在函数中删除了一个断点,它正在触发我的函数。如果我执行以下任何操作,它将停止: 如果我删除,则该按钮不会导致页面刷新 如果我注释掉函数中的代码,它不会导致页面刷新 如果我将按钮标记更改为锚定标记(

  • 假设我想合并一个分离的实体。当我做的时候 entityManager将从数据库加载一个实体(具有与detachedEntity相同的标识符),并将所有数据从detachedEntity复制到新加载的实体。当以后我的事务结束时,这个实体将保存到数据库中。

  • 本文向大家介绍iOS中3DTouch预览导致TableView滑动卡顿问题解决的方法,包括了iOS中3DTouch预览导致TableView滑动卡顿问题解决的方法的使用技巧和注意事项,需要的朋友参考一下 1.发现问题 今天一早来公司,一个同事举着他的6p对我们说:“你看看这是嘛啊...怎么划不动啊...”我一看,果然,滑两下TableView,大概加载2页多就卡飞了...顿时想以是他机子太老了,物

  • 当我hithttp://localhost:4200或http://localhost:4200/forgotPasswordEmail本地环境时,它可以正常工作。 在我的正式生产环境中打开索引页面并单击链接转到另一个页面也可以。但是,当我刷新页面或直接转到

  • 我正在尝试使用、和(不使用)实现实时相机应用程序 所以,我发现这篇教程 http://altitudelabs.com/blog/real-time-filter/ 它是用Objective-C编写的,所以我在Swift4.0中重写了那个代码,xcode9 它看起来工作很好,但有时(很少),它崩溃了以下错误。调用的方法时 EXC_BAD_ACCESS(代码=1,地址+0x************)

  • 问题内容: 我正在用jQuery进行ajax调用。Ajax调用在IE 7中可以正常工作,但是FireFox 3在进行此调用时始终会刷新整个页面。Ajax调用正在发布到ASP.NET页面方法。 jQuery是否有问题,还是我只是缺少某些设置? 调用是通过html按钮的onclick事件进行的。我在进行此ajax调用的方法中尝试了 ,但是FireFox中的完全刷新仍在继续。 我尝试设置async =