我需要将 SimpleMapProperty 添加到 JavaFX 服务类,但我不确定是否使用正确的方法,语法是否正确。请注意,我并不是想让 JavaFX 服务看起来像 Java Bean,我只需要知道如何从枚举 ModuleType(可以是 TYPEA 或 TYPEB)和关联的 boolean 标志监听 EnumMap 的更新。本质上,这可以被认为是封装在单个 EnumMap 中的一对看门狗定时器。
我无法理解如何添加底层 EnumMap 条目(上述每个 ModuleType 应该有 2 个条目)。
public class UDPListenerService extends Service<Void> {
// 'watchdog' property
private final MapProperty<ModuleType, Boolean> watchdog;
// 'watchdog' SimpleMapProperty bound property getter
public ObservableMap<ModuleType, Boolean> getWatchdog() {
return watchdog.get();
}
// 'watchdog' SimpleMapProperty bound property setter
public void setWatchdog(ObservableMap<ModuleType, Boolean> aValue) {
watchdog.set(aValue);
}
// 'watchdog' SimpleMapProperty bound property
public MapProperty<ModuleType, Boolean> watchdogProperty() {
return watchdog;
}
/**
* Constructor
*/
public UDPListenerService()
{
this.watchdog = new SimpleMapProperty<>(
FXCollections.observableHashMap());
}
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
updateMessage("Running...");
while (!isCancelled()) {
try {
Thread.sleep(1000);
Platform.runLater(() -> {
try {
// update do some processing here
// . . .
// pet the watchdog
// setWatchdog
if (testforModuleType==ModuleType.TYPEA) {
// please help with syntax
setWatchdog(ModuleType.TYPEA, false);
} else {
// please help with syntax
setWatchdog(ModuleType.TYPEB, false);
}
} catch (StatusRuntimeException ex) {
// watchdog timed out - listener will
// update gui components
if (testforModuleType==ModuleType.TYPEA) {
// please help with syntax
setWatchdog(ModuleType.TYPEA, true);
} else {
// please help with syntax
setWatchdog(ModuleType.TYPEB, true);
}
}
});
} catch (InterruptedException ex) {}
}
updateMessage("Cancelled");
return null;
}
};
}
}
我使用此类的方式是在 JavaFX Controller 类中添加一个监听器,该监听器根据关联的 boolean 标志是 true 还是 false 来填充 java gui 元素。
最佳答案
通常,只读映射属性用于这种行为,即只有一个 getter 的 ObservableMap
字段。仅修改 map 内容;分配初始 map 后,不会向该字段分配新 map 。
private final ObservableMap<ModuleType, Boolean> watchdog;
public ObservableMap<ModuleType, Boolean> getWatchdog() {
return watchdog;
}
map 本身的修改方式与修改java.util.Map
的方式相同,例如在本例中使用 put
方法。可以观察到变化,例如使用 MapChangeListener
或 Bindings.valueAt
。
此外,EnumMap
可以用作 ObservableMap
的支持 Map
,但要做到这一点需要 observableMap
方法需要使用来代替 observableHashMap
方法。
以下示例根据 ObservableMap
中的值随机选择/取消选择 2 个复选框的值。
private CheckBox checkBoxA;
private CheckBox checkBoxB;
private ObservableMap<ModuleType, Boolean> map;
@Override
public void start(Stage primaryStage) {
checkBoxA = new CheckBox("type A");
checkBoxB = new CheckBox("type B");
map = FXCollections.observableMap(new EnumMap<>(ModuleType.class));
initMapListeners();
Thread t = new Thread(() -> {
Random random = new Random();
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
}
boolean b1 = random.nextBoolean();
boolean b2 = random.nextBoolean();
Platform.runLater(() -> {
map.put(ModuleType.TYPEA, b1);
map.put(ModuleType.TYPEB, b2);
});
}
});
t.setDaemon(true);
t.start();
Scene scene = new Scene(new VBox(10, checkBoxA, checkBoxB));
primaryStage.setScene(scene);
primaryStage.show();
}
以下两个 initMapListeners()
实现都会根据 map 值设置 CheckBox.selected
状态。
private void initMapListeners() {
checkBoxA.selectedProperty().bind(Bindings.valueAt(map, ModuleType.TYPEA));
checkBoxB.selectedProperty().bind(Bindings.valueAt(map, ModuleType.TYPEB));
}
private void initMapListeners() {
map.addListener((MapChangeListener.Change<? extends ModuleType, ? extends Boolean> change) -> {
if (change.wasAdded()) {
if (change.getKey() == ModuleType.TYPEA) {
checkBoxA.setSelected(change.getValueAdded());
} else if (change.getKey() == ModuleType.TYPEB) {
checkBoxB.setSelected(change.getValueAdded());
}
}
});
}
关于java - 将 EnumMap 包装在可观察的 SimpleMapProperty 中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38834966/