- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在尝试学习 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 ......);
}
});
我在这里可以看到三个问题:
ddt
是可变的(可以设置为新值),如果更改,监听器仍将附加到 rowsProperty
原始值,而不是当前值。ddt.setRows(/* another entire list of DDTItems */)
,但不会响应当前列表的更改。所以它不会响应ddt.getRows().add(/* some DDTItem */);
等等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/
我想添加到属性监听器,等待此监听器被调用并删除此监听器。所以我写了下面的代码: ChangeListener listener = (observable, oldValue, newValu
我正在学习更改监听器,并想了解为什么我的部分代码在用户移动 slider 时没有触发更改监听器。 这里是听者。一切都在同一个方法中: ChangeListener lst = new ChangeLi
假设我们有一个带有 fx:include 的根窗口: startwindow.fxml的代码: 单击按钮将窗口更改为新窗口。它的 Controller ,StartW
当我编码时,我添加了以下代码: nameComboBox.valueProperty().addListener(new ChangeListener() { @Override
代码如下: package sample; import javafx.beans.InvalidationListener; import javafx.beans.Observable; impo
我想概括以下模式: setChangeListener = c -> { try { // do something dangerous } catch (final IOEx
我在 slider 上有一个简单的更改监听器。任何人都可以解释为什么当我点击一个新位置时它被解雇了 3 次。在我编写代码将先前的值保存在某处以查看它是否真的改变之前,我想看看是否有另一种方法可以弄清楚
我对 Java 很陌生,在仔细研究文档后,我发现自己陷入了困境。 我有一个小程序,使用 JavaFX MediaPlayer播放 wav 文件。我的播放器对象有一个 currentTimeProper
我有一个 JavaFX 应用程序,其中有一个并发任务。当任务运行时,我想将来自 updateMessage() 的消息附加到 TextArea 因为绑定(bind)不会将新文本附加到 TextArea
场景: 我有一个容器对象,它包含所有继承自 MyContainedObject 类的混合对象。容器类的消费者不能直接访问包含的对象,但我有兴趣知道它们何时发生变化。 设计决策: 监听特定类类型的 Ch
我试图从官方文档的“通知”部分了解 Realm 中的通知类型,当我在多个托管对象中使用 RealmObject addChangeListener 时,只有一个对象发生变化时,所有这些通知类型都会被调
我需要检测所选标签何时发生变化,并获取其索引。 以下代码有效,但它触发 println 的次数与当前加载的选项卡数量一样多: tabbedPane.addChangeListener(new Chan
在我的 JavaFX 应用程序中,我在 TreeView 中使用 Checkboxes 来更改节点的可见性。 选中复选框 = 一些节点可见 取消选中复选框 = 一些节点不可见 但是,在特殊情况下,应该
我只关心属性是否已更改,而不是新值。 注册 InvalidationListener 而不是 ChangeListener 是否有利? 我假设对属性的更改首先会使该属性无效并通知所有无效监听器。仅当注
我不知道为什么会收到警告“来自类型 new ChangeListener(){} 的方法 tabChanged(ChangeEvent) 从未在本地使用” private void setUpTabb
我正在寻找代码中的功能,以便我可以在几秒钟内输入完整内容simpleTextField 中的名称,我需要它,因为如果我输入例如: 我输入 R - 然后方法改变正在执行它的任务 我输入 RR - 然后方
我确实有一个由多个可观察的 SimpleDoubleProperty 组成的模型,我现在有一个程序,它根据可观察属性的变化运行一个函数。 我现在有一个函数calculateThings,它会在变化时被
如何打印顶部的JLabel? import java.awt.BorderLayout; import java.awt.EventQueue; import javax.swing.JFrame;
我在舞台上添加了一个表,但无法获得点击监听器来触发它: Table table = new Table(); table.setX(0); table.setY(0); table.setWidth(
我希望 ObservableList 中有一个粗体的标题。我将其设置为粗体,但在选择它时会遇到异常 block ,因为它不是字符串。我可以将其他项目设为文本,但 ChangeListener 需要一个
我是一名优秀的程序员,十分优秀!