I\'m kinda new to JavaFX and currently trying to do a Calendar application for a school project. I was wondering if there was a way to concatenate a fx:id
Various possible solutions:
You could use reflection, but that would be ugly and I wouldn't advise it.
Normally, if you have a lot of things, you put them in a collection like a list or array. The label will be a child of some layout pane, so you can get the children of the pane and lookup an item by index with something like:
((Label) parent.getChildren().get(0)).setText("Text");
If the label has been assigned a css id then you can use that to lookup the label.
For example, in your FXML define:
<Label text="hello" fx:id="Box01" id="Box01"/>
Then you can lookup the label using:
String boxNum = "01";
Label box = (Label) parent.lookup("#Box" + boxNum);
Just refer to the item by it's reference:
@FXML private Label box01;
box01.setText("Test");
Aside: Please use camel case as per standard Java conventions.
In addition to the methods mentioned by @jewelsea here are 2 more ways to do this:
Create & inject a Map
containing the boxes as values from the fxml:
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxml.Controller">
<children>
<Label text="foo" fx:id="a"/>
<Label text="bar" fx:id="b"/>
<Spinner fx:id="number">
<valueFactory>
<SpinnerValueFactory.IntegerSpinnerValueFactory min="1" max="2"/>
</valueFactory>
</Spinner>
<Button text="modify" onAction="#modify"/>
<fx:define>
<HashMap fx:id="boxes">
<box1>
<fx:reference source="a"/>
</box1>
<box2>
<fx:reference source="b"/>
</box2>
</HashMap>
</fx:define>
</children>
</VBox>
Controller
public class Controller {
private Map<String, Label> boxes;
@FXML
private Spinner<Integer> number;
@FXML
private Label box1;
@FXML
private Label box2;
@FXML
private void modify(ActionEvent event) {
boxes.get("box"+number.getValue()).setText("42");
}
}
Pass the namespace
of the FXMLLoader
, which is a Map<String, Object>
mapping fx:id
s to the associated Object
s, to the controller:
<VBox xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxml.Controller">
<children>
<Label text="foo" fx:id="box1"/>
<Label text="bar" fx:id="box2"/>
<Spinner fx:id="number">
<valueFactory>
<SpinnerValueFactory.IntegerSpinnerValueFactory min="1" max="2"/>
</valueFactory>
</Spinner>
<Button text="modify" onAction="#modify"/>
</children>
</VBox>
Controller
public class Controller implements NamespaceReceiver {
private Map<String, Object> namespace;
@FXML
private Spinner<Integer> number;
@FXML
private Label box1;
@FXML
private Label box2;
@FXML
private void modify(ActionEvent event) {
((Label)namespace.get("box" + number.getValue())).setText("42");
}
@Override
public void setNamespace(Map<String, Object> namespace) {
this.namespace = namespace;
}
}
public interface NamespaceReceiver {
public void setNamespace(Map<String, Object> namespace);
}
Code for loading the fxml:
public static <T> T load(URL url) throws IOException {
FXMLLoader loader = new FXMLLoader(url);
T result = loader.load();
Object controller = loader.getController();
if (controller instanceof NamespaceReceiver) {
((NamespaceReceiver) controller).setNamespace(loader.getNamespace());
}
return result;
}