经过几个小时的寻找答案,我终于放弃了。
我有一个带有以下ComboBox的FXML表单:

<ComboBox fx:id="cboTipo" disable="true" prefWidth="247.0" promptText="Tipo de obra..." GridPane.columnIndex="1" GridPane.rowIndex="2" />


将其注入JavaFX控制器类中:

    @FXML
    public ComboBox<Tobra> cboTipo;


该组合显示了使用Eclipselink 2.7和JPA 2.2从嵌入式H2数据库加载的Tobra列表(代表:西班牙人Tipo de Obra)。

我没有向用户显示Tobra.toString的值,而是在初始化时设置了一个转换器:

@Override
public void initialize(URL url, ResourceBundle rb) {
    ...
    Objects.requireNonNull(cboTipo, "cboTipo not injected");
    ...
    cboTipo.setConverter(new StringConverter<Tobra>() {
        @Override
        public String toString(Tobra object) {
            return object.getCod() + ": " + object.getNombre();
        }

        @Override
        public Tobra fromString(String string) {
            return new Tobra(string);
        }
    });
   ...
}


我有一个实现Task<List<Tobra>>的内部类,因此我可以在后台加载数据。然后,就成功了:

task.setOnSucceeded(evt ->
    cboTipo.setItems(FXCollections.observableArrayList(task.getValue()))
);


当然,当显示表单时,我在线程内运行任务:

 new Thread(task).start();


在测试代​​码之前,一切似乎都可以正常工作。不管我单击哪个值,总是将所选值重置为第一项。我试图从代码中强制使用某些值,并且该值显示在组合框中,但是当用户单击组合以选择另一个值时,再次将所选值重置为“第一项”。
仅当使用带有类型参数的ComboBox时,才会发生此行为。当我创建不带类型参数的组合框,然后添加字符串值时,如下所示:

 cboTipo.getItems().clear();
 cboTipo.getItems().addAll(
  tobraList.stream().map(x
       -> x.getCod() + ": " + x.getNombre())
  .toArray());


一切正常。

因此,我尝试使用POJO Tobra进行相同的操作而不映射到字符串:

 cboTipo.getItems().clear();
 cboTipo.getItems().addAll(tobraList);


但是问题再次出现。我也尝试过声明不带类型参数的ComboBox cboTipo,但这都不起作用。
我的POJO Tobra以这种方式覆盖equals方法:

@Override
public boolean equals(Object object) {
    if (!(object instanceof Tobra)) {
        return false;
    }
      var other = (Tobra) object;
    return ((this.cod == null && other.cod != null)
            || (this.cod != null && !this.cod.equals(other.cod)));
}


我究竟做错了什么?

PS:
我还尝试按照以下建议设置自己的电池工厂:
Javafx combobox with custom object displays object address though custom cell factory is used

并尝试对其进行调试,我意识到问题不在于组件的呈现,因为ComboBox的value属性在选择后永远不会更新。

最佳答案

您的equals()方法很奇怪。

return ((this.cod == null && other.cod != null)
        || (this.cod != null && !this.cod.equals(other.cod)));


让我们分手吧。第1部分:

(this.cod == null && other.cod != null)


如果此codTobranull,而另一个codTobra不是null,则此部分是true

现在,发生这种情况时,整个表达式将返回true,因为您有一个||运算符。

让我们看第二部分。

(this.cod != null && !this.cod.equals(other.cod))


如果此codTobra不是null,而另一个codTobra不相等,则此部分为true

再次看起来相反。

您很可能需要!整个表达式。或者,您可以使用Objects.equals(this.cod, other.cod),它会为您检查null。

最后,请确保您还覆盖了hashCode()并返回了不会破坏equals()合同的正确值。阅读Javadoc以获得更多详细信息。

08-03 13:30