Javafx中未触发ChangeListener
我正在尝试学习JavafX,从而学习如何使用属性进行思考 我有一个bean,用于更新TableView,如下所示:Javafx中未触发ChangeListener,java,javafx,properties,changelistener,Java,Javafx,Properties,Changelistener,我正在尝试学习JavafX,从而学习如何使用属性进行思考 我有一个bean,用于更新TableView,如下所示: public class DDTTabController extends DefaultTabController implements Initializable { .... @FXML private TableView<DDTTableView> ddtTable; .... @FXML private Tabl
public class DDTTabController extends DefaultTabController implements Initializable {
....
@FXML
private TableView<DDTTableView> ddtTable;
....
@FXML
private TableColumn<DDTTableView, String> rifColumn;
....
}
@Override
public void initialize(URL url, ResourceBundle rb) {
....
rifColumn.setCellValueFactory(cellData -> cellData.getValue().getRifProperty());
....
}
这是我用于视图的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;
}
}
您可以看到,我只使用第二个构造函数(带参数的构造函数)
现在的问题是,即使在ddtbean中更新了Rows属性,Rif属性desn也不会得到重建,因为changelister不会触发,我无法理解为什么
谁能给我点启示吗
谢谢。在
DDTTableView
构造函数中,将ddt
属性的值设置为作为参数传递的值,然后将侦听器添加到ddt
当前值的rowsProperty
:
this.ddt.get().getRowsProperty().addListener(new ChangeListener() {
@Override
public void changed(ObservableValue observable, Object oldValue, Object newValue) {
System.out.println("bip!");
rif.set(...... buildString ......);
}
});
我在这里可以看到三个问题:
ddt
是可变的(可以设置为新值),如果更改,侦听器仍将附加到原始值的rowsProperty
,而不是当前值ddt.setRows(/*另一个完整的ddt列表*/)
,但不会响应对当前列表的更改。因此它不会响应ddt.getRows().add(/*一些DDTItem*/)代码>,等等
DDTTableView
构造函数不添加侦听器(只有接受参数的构造函数才添加侦听器)ddt
属性,并在其值更改时移动侦听器
对于第二个问题,我建议不要使列表可变,而只是可修改。如果需要,您可以随时执行ddt.getRows().setAll(someOtherList)
,而不必执行ddt.getRows().setAll(someOtherList)
,这基本上具有相同的效果1。然后只需注册一个ListChangeListener
就可以访问列表
通过移动将侦听器附加到默认构造函数(由另一个构造函数调用)的代码,可以很容易地解决第三个问题
您还应该修复方法名称,以便它们与
即:
公共级滴滴涕{
//...
私有最终可观察列表行;
// ...
公共滴滴涕(){
// ...
this.rows=FXCollections.observableArrayList();
// ...
}
公共可观察列表getRows(){
返回行。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;
}
}
私有类DDTTableView{
滴滴涕;
私人财产接触;
私有财产;
公共DDTTableView(){
this.ddt=新的SimpleObject属性();
this.contact=新的SimpleObject属性();
this.rif=新的SimpleStringProperty(“”);
this.setContact(dataManager.getContactForCodeType(o.getAnaTipe(),o.getAnaCode().trim());
ListChangeListener rowsListener=(ListChangeListener.change您的意思是更新调用setRighe()的rows属性吗
?这实际上应该是可行的。当更改侦听器未触发时,通常会由于弱引用而对属性进行垃圾收集。但由于所有属性都存储在字段中,所以这不应该是问题所在。
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 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;
}
}