我需要向JavaFX服务类中添加一个SimpleMapProperty,但是我不确定是否使用了正确的方法来使用正确的语法。请注意,我并不是想使JavaFX服务看起来像Java Bean,我只需要知道如何从枚举ModuleType(可以是TYPEA或TYPEB)和关联的布尔标志中侦听对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控制器类中,在该类中,添加一个侦听器,该侦听器根据关联的布尔标志是true还是false来填充java gui元素。

最佳答案

通常,只读map属性用于这种行为,即,仅具有getter的ObservableMap字段。只有地图的内容被修改;分配初始地图后,不会将新地图分配给该字段。

private final ObservableMap<ModuleType, Boolean> watchdog;

public ObservableMap<ModuleType, Boolean> getWatchdog() {
    return watchdog;
}


映射本身的修改方式与java.util.Map的修改方式相同,例如在这种情况下,使用put方法。可以观察到变化,例如使用MapChangeListenerBindings.valueAt

此外,EnumMap可以用作Map的后备ObservableMap,但是要执行此操作,需要使用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()的以下两个实现都将基于映射值设置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 - 在可观察的SimpleMapProperty中包装EnumMap,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/38834966/

10-13 05:53