Javafx中未触发ChangeListener

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

我正在尝试学习JavafX,从而学习如何使用属性进行思考

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

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;
        }
    }