gpt4 book ai didi

java - ChangeListener 在 Javafx 中未触发

转载 作者:行者123 更新时间:2023-11-30 06:58:31 29 4
gpt4 key购买 nike

我正在尝试学习 JavafX 以及如何用属性来思考。

我有一个用于更新 TableView 的 bean,如下所示:

public class DDTTabController extends DefaultTabController implements Initializable {
....
@FXML
private TableView<DDTTableView> ddtTable;
....
@FXML
private TableColumn<DDTTableView, String> rifColumn;
....
}

等等。我像这样初始化我的 Controller :

@Override
public void initialize(URL url, ResourceBundle rb) {
....
rifColumn.setCellValueFactory(cellData -> cellData.getValue().getRifProperty());
....
}

这是我用于 View 的 bean:

private class DDTTableView {

private ObjectProperty<DDT> ddt;
private ObjectProperty<Contact> contact;
private StringProperty rif;

public DDTTableView() {
this.ddt = new SimpleObjectProperty<>();
this.contact = new SimpleObjectProperty<>();
this.rif = new SimpleStringProperty("");
}

public DDTTableView(DDT o) {
this();

this.setDdt(o);
this.setContact(dataManager.getContactForCodeType(o.getAnaTipe(), o.getAnaCode().trim()));

this.ddt.get().getRowsProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
System.out.println("bip!");
rif.set(...... buildString ......);
}
});

}

public StringProperty getRifProperty() {
return this.rif;
}

public String getRif() {
return this.rif.get();
}

public void setRif(String r) {
this.rif.set(r);
}

public ObjectProperty<DDT> getDdtProperty() {
return ddt;
}

public DDT getDdt() {
return ddt.get();
}

public void setDdt(DDT ddt) {
this.ddt.set(ddt);
}

public ObjectProperty<Contact> getContactProperty() {
return contact;
}

public Contact getContact() {
return contact.get();
}

public void setContact(Contact contact) {
this.contact.set(contact);
}

@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + Objects.hashCode(this.ddt);
return hash;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DDTTableView other = (DDTTableView) obj;
if (!Objects.equals(this.ddt, other.ddt)) {
return false;
}
return true;
}
}

DDT bean :

public class DDT {
....
private ObjectProperty<ObservableList<DDTItem>> rows;
....
}

public DDT() {
....
this.rows = new SimpleObjectProperty<>(FXCollections.observableArrayList());
....
}

public ObjectProperty<ObservableList<DDTItem>> getRowsProperty() {
return rows;
}

public ObservableList<DDTItem> getRows() {
return rows.get();
}

public void setRighe(ObservableList<DDTItem> r) {
this.rows.set(r);
}
....
}

最后是我将数据传递给 Controller ​​的入口点:

public void setMainApp(AppWindow mainApp, MDIWindow win, MDICanvas can) {
super.setMainApp(mainApp, win, can);

dataManager.getDDT().stream().forEach((ddt) -> {
actualDDT.add(new DDTTableView(ddt));
});
}

你可以看到我只使用了第二个构造函数(带有参数的构造函数)。

现在的问题是,即使在 DDT bean 中更新了 Rows 属性,Rif 属性也不会被重建,因为 ChangeListener 不会触发,我无法理解为什么。

有人可以解释一下吗?

谢谢。

最佳答案

DDTTableView构造函数中,您设置 ddt 的值属性到作为参数传递的值,然后将监听器添加到 rowsProperty 当前值 ddt :

this.ddt.get().getRowsProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
System.out.println("bip!");
rif.set(...... buildString ......);
}
});

我在这里可以看到三个问题:

  1. ddt是可变的(可以设置为新值),如果更改,监听器仍将附加到 rowsProperty 原始值,而不是当前值。
  2. 您仅监听整个行列表的更改。 IE。您的听众将回复 ddt.setRows(/* another entire list of DDTItems */) ,但不会响应当前列表的更改。所以它不会响应ddt.getRows().add(/* some DDTItem */);等等
  3. 您的默认值 DDTTableView构造函数不会添加监听器(只有带参数的构造函数才会添加监听器)。

对于第一个问题,你需要观察你的ddt属性并在其值发生变化时移动监听器。

对于第二个问题,我建议不要使列表可变,而只是可修改。而不是ddt.setRows(someOtherList) (如果您需要的话),您可以随时执行 ddt.getRows().setAll(someOtherList) ,其效果基本相同1。然后只需注册一个ListChangeListener将列出 list 。

通过移动将监听器附加到默认构造函数(由另一个构造函数调用)的代码,可以轻松解决第三个问题。

您还应该修复您的方法名称,以便它们与 JavaFX properties pattern 匹配.

即:

public class DDT {

//...

private final ObservableList<DDTItem> rows;

// ...


public DDT() {

// ...

this.rows = FXCollections.observableArrayList();

// ...
}


public ObservableList<DDTItem> getRows() {
return rows.get();
}

// ...
}

现在

private class DDTTableView {

private ObjectProperty<DDT> ddt;
private ObjectProperty<Contact> contact;
private StringProperty rif;

public DDTTableView() {
this.ddt = new SimpleObjectProperty<>();
this.contact = new SimpleObjectProperty<>();
this.rif = new SimpleStringProperty("");

this.setContact(dataManager.getContactForCodeType(o.getAnaTipe(), o.getAnaCode().trim()));

ListChangeListener<DDTItem> rowsListener = (ListChangeListener.Change<? extends DDTItem> change) -> {
rif.set(/* buildString */);
};

this.ddt.addListener((obs, oldDdt, newDdt) -> {
if (oldDdt != null) {
oldDdt.getRows().removeListener(rowsListener);
}
if (newDdt != null) {
newDdt.getRows().addListener(rowsListener);
}
});


}

public DDTTableView(DDT o) {
this();

this.setDdt(o);

}

public StringProperty rifProperty() {
return this.rif;
}

public String getRif() {
return this.rif.get();
}

public void setRif(String r) {
this.rif.set(r);
}

public ObjectProperty<DDT> ddtProperty() {
return ddt;
}

public DDT getDdt() {
return ddt.get();
}

public void setDdt(DDT ddt) {
this.ddt.set(ddt);
}

public ObjectProperty<Contact> contactProperty() {
return contact;
}

public Contact getContact() {
return contact.get();
}

public void setContact(Contact contact) {
this.contact.set(contact);
}

@Override
public int hashCode() {
int hash = 5;
hash = 89 * hash + Objects.hashCode(this.ddt);
return hash;
}

@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final DDTTableView other = (DDTTableView) obj;
if (!Objects.equals(this.ddt, other.ddt)) {
return false;
}
return true;
}
}

1如果您确实需要setRows(...)功能,您可以使用 ListProperty<DDTItem> 而不是ObjectProperty<ObservableList<DDTItem>> 。这将通知ListChangeListener s 如果基础列表通过 setRows(...) 更改或者如果当前列表已通过 getRows().add(...) 修改等等。不过,这种情况的用例非常罕见,通常只需拥有一个不可变的可修改列表就足够了,如上面的代码所示。

关于java - ChangeListener 在 Javafx 中未触发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41361212/

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