gpt4 book ai didi

java - JavaFX 中现有 java bean 的异步绑定(bind)

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:02:16 25 4
gpt4 key购买 nike

我正在将现有的 Swing 项目迁移到 JavaFX。该项目有很多使用 PropertyChangeSupport 的旧式 Java bean,这些都在各种后台线程上更新。

  • 我想利用 beans 适配器 (javafx.beans.property.adapter) 来连接新 View 。然而,这失败了,因为模型没有在 FX 应用程序线程上更新。

  • 理想情况下,我希望单独保留更新模型的现有代码,而不是包装在 Platform.runLater 中

到目前为止,我的解决方案是使用我自己的 AsyncBinding 类,它接受由 beans 适配器创建的现有 ObservableValue,监听它,并在适当的线程上触发更改,但是不得不在任何地方添加它感觉很乱

  • 是否有我缺少的内置方法?
  • 我可以采用更清洁的方法吗?

典型 View

public class AsyncIssue extends Application {

public static void main(String[] args) {
launch(args);
}

@Override
public void start(Stage primaryStage) throws Exception {
FooBean bean = new FooBean();
TextField field = new TextField();

field.textProperty().bind(
JavaBeanIntegerPropertyBuilder.create().bean(bean).name("x")
.build().asString("%03d"));
primaryStage.setScene(new Scene(new VBox(field)));
primaryStage.show();

Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
try {
// simulate background work
bean.setX(bean.getX() + 1);
} catch (Throwable e) {
// Executors consume exception by default
e.printStackTrace();
throw e;
}
}, 0, 1, TimeUnit.SECONDS);

}
}

典型Bean

public class FooBean {
private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public static final String PROPERTY_X = "x";
private int x;
public int getX() {
return x;
}
public void setX(int x) {
int oldValue = this.x;
this.x = x;
pcs.firePropertyChange(PROPERTY_X, oldValue, x);
}
public void addPropertyChangeListener(PropertyChangeListener listener) {
pcs.addPropertyChangeListener(listener);
}
public void removePropertyChangeListener(PropertyChangeListener listener) {
pcs.removePropertyChangeListener(listener);
}
}

最佳答案

目前我最好的解决方案

  • 创建一个代理 ObservableValue 的实用程序类 AsyncBinding
  • 监听底层可观察对象,在正确的线程上分派(dispatch)给监听器。

用法

field.textProperty().bind(
AsyncBinding.bind(JavaBeanIntegerPropertyBuilder.create()
.bean(bean).name("x").build().asString("%03d")));

异步绑定(bind)

public class AsyncBinding<T> implements ObservableValue<T> {

private ObservableValue<T> value;
private InvalidationListener invalidationListener;
private ChangeListener<T> changeListener;
private List<InvalidationListener> invalidationListeners = new ArrayList<InvalidationListener>(
1);
private List<ChangeListener<? super T>> changeListeners = new ArrayList<ChangeListener<? super T>>(
1);

public static <T> ObservableValue<T> bind(ObservableValue<T> toWrap) {
return new AsyncBinding<T>(toWrap);
}

private AsyncBinding(ObservableValue<T> value) {
this.value = value;
invalidationListener = new InvalidationListener() {
@Override
public void invalidated(Observable observable) {
Runnable fire = () -> {
synchronized (invalidationListeners) {
for (InvalidationListener listener : invalidationListeners) {
listener.invalidated(observable);
}
}
};
if (Platform.isFxApplicationThread()) {
fire.run();
} else {
Platform.runLater(fire);
}
}
};
value.addListener(invalidationListener);

changeListener = new ChangeListener<T>() {
@Override
public void changed(ObservableValue<? extends T> observable,
T oldValue, T newValue) {
Runnable fire = () -> {
synchronized (changeListeners) {
for (ChangeListener<? super T> listener : changeListeners) {
listener.changed(observable, oldValue, newValue);
}
}
};
if (Platform.isFxApplicationThread()) {
fire.run();
} else {
Platform.runLater(fire);
}
}
};

value.addListener(changeListener);
}

@Override
public void addListener(InvalidationListener listener) {
invalidationListeners.add(listener);
}

@Override
public void removeListener(InvalidationListener listener) {
invalidationListeners.remove(listener);
}

@Override
public void addListener(ChangeListener<? super T> listener) {
changeListeners.add(listener);
}

@Override
public void removeListener(ChangeListener<? super T> listener) {
changeListeners.remove(listener);
}

@Override
public T getValue() {
return value.getValue();
}
}

关于java - JavaFX 中现有 java bean 的异步绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27380082/

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