我们将JavaFX集成到一个包含许多_____84694_ Java bean的大型遗留代码库中,即使用 java.beans.PropertyChangeSupport
实现的类型 .
JavaFX不支持更新这些样式的bean,只支持初始值,如javafx.scene.control.cell.PropertyValueFactory中所述
如果不存在与此模式匹配的方法,则会尝试调用get()或is()(即上例中的getFirstName()或isFirstName()) . 如果存在与此模式匹配的方法,则此方法返回的值将包装在ReadOnlyObjectWrapper中并返回到TableCell . 但是,在这种情况下,这意味着TableCell将无法观察ObservableValue的更改(如上面第一种方法中的情况) .
将bean升级到属性API不是一种选择,因为它们位于一个单独的代码库中,我们不希望添加JavaFX依赖项,因为旧的Java 6项目仍在使用它 .
我的问题是,如何在更改属性时更新TableView,而无需在表中的所有单个bean上添加/删除侦听器 .
我正在考虑创建我自己的PropertyValueFactory版本,它支持这个,但我想知道是否还有其他可能的解决方案 .
我已经制作了两个例子来说明这一点 .
使用老式bean的TableView
public class OldBeanTableView extends Application {
public class OldBean {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public static final String PROPERTY_NAME_FOO = "foo";
private int foo = 99;
public int getFoo() {
return foo;
}
public void setFoo(int foo) {
int oldValue = this.foo;
this.foo = foo;
pcs.firePropertyChange(PROPERTY_NAME_FOO, oldValue, foo);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<OldBean> beans = FXCollections.observableArrayList();
beans.add(new OldBean());
TableView<OldBean> tableView = new TableView<>();
TableColumn<OldBean, Integer> column = new TableColumn<OldBeanTableView.OldBean, Integer>();
tableView.getColumns().add(column);
column.setCellValueFactory(new PropertyValueFactory<>("foo"));
tableView.setItems(beans);
primaryStage.setScene(new Scene(tableView));
primaryStage.show();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> beans.get(0).setFoo(beans.get(0).getFoo() + 1), 0,
1, TimeUnit.SECONDS);
}
}
使用新bean的TableView
public class NewBeanTableView extends Application {
public class NewBean {
private IntegerProperty fooProperty = new SimpleIntegerProperty(0);
public int getFoo() {
return fooProperty.get();
}
public void setFoo(int foo) {
fooProperty.set(foo);
}
public IntegerProperty fooProperty() {
return fooProperty;
}
}
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
ObservableList<NewBean> beans = FXCollections.observableArrayList();
beans.add(new NewBean());
TableView<NewBean> tableView = new TableView<>();
TableColumn<NewBean, Integer> column = new TableColumn<NewBeanTableView.NewBean, Integer>();
tableView.getColumns().add(column);
column.setCellValueFactory(new PropertyValueFactory<>("foo"));
tableView.setItems(beans);
primaryStage.setScene(new Scene(tableView));
primaryStage.show();
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> beans.get(0).setFoo(beans.get(0).getFoo() + 1), 0,
1, TimeUnit.SECONDS);
}
}
2 回答
使用JavaBeanProperty作为valueFactory的一个非常快速的示例:
请注意,bean必须有方法add / removePropertyChangeListeners(无论如何你的真正的bean都会:-)才能工作 .
推断kleopatra对通用解决方案的回答 .
用法