In the midst of developing a JavaFX application project, this is my first real stumper and I don't even know how to properly say what I'm trying to do because I don't know the names of the techniques I'm trying to utilize.
In my application, I have multiple custom components so I can build a more complex scene. This problem involves 3 control components; a PrimaryControl component (SplitPane) which contains a MenuComponent and an ActivityComponent (both custom) which changes based on the selection of radio buttons set up in the MenuComponent.
How can I get the MenuControl class to "emit" the performed action when a radio button in the ToggleGroup (from that component) is changed which will then be handled by a function in the parent component PrimaryControl so that it may change which ActivityComponent is visible/active? Bear with me.
primary_control.fxml
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml">
<MenuControl onToggleGroupButtonSelectionChanged="#onChange"/>
<ActivityOneControl fx:id="one" isVisible="true"/>
<ActivityTwoControl fx:id="two" isVisible="false"/>
...
</fx:root>
menu_control.fxml
<fx:root type="javafx.scene.layout.VBox" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/10.0.2-internal">
<GridPane alignment="CENTER" hgap="10" vgap="10">
<padding><Insets bottom="25" left="25" right="25" top="15" /></padding>
<Label text="Select A Task" GridPane.columnIndex="0" GridPane.rowIndex="0">
<font><Font name="System Bold" size="13.0" /></font>
</Label>
<fx:define>
<ToggleGroup fx:id="menuSelection"/>
</fx:define>
<RadioButton fx:id="one" text="one" GridPane.columnIndex="0" GridPane.rowIndex="1" toggleGroup="$menuSelection">
</RadioButton>
<RadioButton fx:id="two" text="two" GridPane.columnIndex="0" GridPane.rowIndex="2" toggleGroup="$menuSelection">
</RadioButton>
<RadioButton fx:id="three" text="three" GridPane.columnIndex="0" GridPane.rowIndex="3" toggleGroup="$menuSelection">
</RadioButton>
</GridPane>
</fx:root>
How do I create a listener in my MenuControl java class that will be able to detect the ToggleGroup selection change, then emit that change to onToggleGroupButtonSelectionChanged="#onChange"
so I can handle the button selection from the PrimaryControl java class? I remember doing this type of thing in Angular and it was pretty easy but for some reason, I can't find any information on how to do this is Java. Is this what's known as dependency injection?
I found this link and tried to implement for my problem but unsuccessful as nothing was explained and a different event was being listened for JavaFX 2.0 - create action handler for custom component in FXML.
PrimaryController.java (same as MenuControl.java)
public class PrimaryControl extends VBox {
public DashboardControl() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("primary_control.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
@FXML
protected void onChange() {
System.out.println("change activity");
}
}
Thank you in advance to anyone helping me with this.
public enum SelectionMode {
ONE, TWO, THREE
}
ReadOnlyObjectProperty
) :private ReadOnlyObjectWrapper<SelectionMode> selectionMode
= new ReadOnlyObjectWrapper<>(this, "selectionMode");
public final ReadOnlyObjectProperty<SelectionMode> selectionModeProperty() {
return selectionMode.getReadOnlyProperty();
}
private final SelectionMode getSelectionMode() {
return selectionMode.get();
}
initialize
method. Note that I am using setUserData
and getUserData
methods, otherwise, you need to need to have an if clause for each radio button you have:@Override
public void initialize(URL location, ResourceBundle resources) {
one.setUserData(SelectionMode.ONE);
two.setUserData(SelectionMode.TWO);
three.setUserData(SelectionMode.THREE);
selectionMode.bind(Bindings.createObjectBinding(() -> {
Toggle selectedToggle = menuSelection.getSelectedToggle();
return (SelectionMode) selectedToggle.getUserData();
}, menuSelection.selectedToggleProperty()));
}
<MenuControl fx:id="menu"/>
.
Then you can just assign a ChangeListener
and get notified every time the selection is changed:menu.selectionModeProperty().addListener((observable, oldValue, newValue) -> {
// write your code here
});
Note: you can initialize user data in your fxml like this (instead of doing it in initialize
method):
<RadioButton fx:id="one" text="one" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="ONE"/>
</userData>
</RadioButton>
<RadioButton fx:id="two" text="two" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="TWO"/>
</userData>
</RadioButton>
<RadioButton fx:id="three" text="three" toggleGroup="$menuSelection">
<userData>
<SelectionMode fx:constant="THREE"/>
</userData>
</RadioButton>