2016-08-08 7 views
1

Ich muss eine SimpleMapProperty zu einer JavaFX-Serviceklasse hinzufügen, aber ich bin mir nicht sicher über die korrekte Syntax, wenn ich den richtigen Ansatz verwende. Beachten Sie, dass ich nicht versuche, den JavaFX-Service wie eine Java-Bean aussehen zu lassen. Ich muss nur wissen, wie man Updates für eine EnumMap von einem Enum ModuleType (das kann TYPEA oder TYPEB sein) und einem zugehörigen booleschen Flag abhört. Im Wesentlichen kann dies als ein Paar Watchdog-Timer in einer einzigen EnumMap gedacht werden.Wrapping einer EnumMap in einer beobachtbaren SimpleMapProperty

Ich habe Probleme zu verstehen, wie die zugrunde liegenden EnumMap-Einträge hinzugefügt werden (es sollte 2 - eine für jeden oben beschriebenen ModuleType sein).

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; 
      } 
     }; 
    } 
} 

Die Art und Weise diese Klasse I in der JavaFX Controller-Klasse verwenden ist, wo ich ein Listener Element hinzufügen, das Java-GUI abhängig davon, ob die zugehörige boolesches Flag wahr oder falsch ist auffüllt.

+2

Sind Sie sicher, dass Sie die Karte und nicht einfach ändern, es ersetzen wollen. Im letzteren Fall wäre eine readonly map -Eigenschaft (d. H. Eine 'ObservableMap' mit nur einem Getter) besser geeignet ... – fabian

+0

@fabian Die Änderungen an dem von ObservableMap eingeschlossenen zugrunde liegenden Wert interessieren mich für Änderungen. Hast du ein Beispiel, wie ich das machen könnte? Ist es nur eine Frage des Konstruierens der FXCollections.observableHashMap (enumMapdefault), wo enumMapDefault eine Standardzuordnung mit den 2 Schlüsseln enthält, die in der Frage beschrieben werden – johnco3

Antwort

1

Normalerweise wird für diese Art von Verhalten eine readonly-Map-Eigenschaft verwendet, d. H. Ein ObservableMap-Feld mit nur einem Getter. Nur der Inhalt der Karte wird geändert. Nach der Zuweisung der ersten Karte wird dem Feld keine neue Karte zugewiesen.

private final ObservableMap<ModuleType, Boolean> watchdog; 

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

Die Karte selbst ist die gleiche Art und Weise modifiziert ein java.util.Map modifiziert werden würde, z.B. in diesem Fall mit der put Methode. Änderungen können z.B. unter Verwendung eines MapChangeListener oder Bindings.valueAt.

Außerdem EnumMap können als Träger Map für eine ObservableMap verwendet werden, aber dies der observableMap Methode tun muss, um anstelle des observableHashMap Verfahren verwendet werden.

Im folgenden Beispiel werden nach dem Zufallsprinzip Werte von 2 Ankreuzfeldern basierend auf Werten in einer ObservableMap ausgewählt/abgewählt.

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(); 
} 

Sowohl die folgenden Implementierungen von initMapListeners() würden beide setzen die CheckBox.selected Staaten auf der Grundlage der Kartenwerte.

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()); 
      } 
     } 
    }); 
} 
Verwandte Themen