javajavafxjavafx-2javafx-8

Bind ToggleGroup bidirectionally in javafx


Imagine having an enum defining mouse-modes:

public enum MouseMode {
SELECTION,
EDITING,
DELETING }

And imagine having a toggle-group made of 3 buttons:

    ToggleButton selection = new ToggleButton("Select");
    ToggleButton editing = new ToggleButton("Edit");
    ToggleButton deleting = new ToggleButton("Delete");
    ToggleGroup mouseSelection = new ToggleGroup();

I want a field MouseMode currentMode to be bidirectionally linked to the toggle-group. Whenever a toggle is set, currentMode is switched accordingly but also if some external process changes currentMode (maybe a key press) then the togglegroup adapts accordingly.

I can do this with 2 listeners but I wonder if there is a way to create a custom bidirectional map.


Solution

  • I don't think there is a way to do this directly. While a general-purpose

    Bindings.bindBidirectional(Property<S> property1, Property<T> property2, Function<S,T> mapping, Function<T,S> inverseMapping)
    

    might make a good addition to the API, even that wouldn't help in this case as the ToggleGroup's selectedProperty is read only (since selection needs to be handled when each Toggle's setSelected(...) method is invoked, as well as by the ToggleGroup's selectedProperty).

    Using a couple of listeners is the way to go in this case.

    The closest thing to the "custom bidirectional map" is the

    Bindings.bindBiDirectional(StringProperty stringProperty, ObjectProperty<T> otherProperty, StringConverter<T> converter)
    

    method. In the case where you have an (writeable) ObjectProperty<S> and (writeable) ObjectProperty<T> you can in theory use two bidirectional bindings and an intermediate StringProperty to bind them together. In practice, this is almost always more code than just using two listeners, and is also less efficient.