Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

adding elements defined in FXML to list with loop

I have a lot of Objects with names a1, a2, a3, ... I need to put them into List, so that it was simplier to work with them, will I do it somehow with loop?

My attempt was:

List<SomeObject> list = new LinkedList<SomeObject>();
for (int i=0; i<1000; i++){
    String varName = "a"+i;
    list.add((SomeObject) varName);
}

Does anyone have suggestions in this case? Create variables inside loop is not a solution, because they are a part of .fxml document. Or give me an advice how to create that with loop, for it create lines in .fxml parallel to adding in loop new objects.

To be more understandable .fxml file looks like

  <SomeObject fx:id="a1" *other props* />
  <SomeObject fx:id="a2" *other props* />
  <SomeObject fx:id="a3" *other props* />
  <SomeObject fx:id="a4" *other props* />

Thanks a lot in advice!

like image 892
Vitali Kuzmin Avatar asked Aug 02 '26 22:08

Vitali Kuzmin


1 Answers

If you have that many items, it's probably best to initialize them using Java, rather than using FXML. For example, instead of:

<FlowPane fx:id="container" minWidth="..." minHeight="...">
    <Label fx:id="label1" text="Label 1"/>
    <Label fx:id="label2" text="Label 2"/>
    <Label fx:id="label3" text="Label 3"/>

    <!-- ... -->

    <Label fx:id="label1000" text="Label 1000"/>
</FlowPane>

and a controller

public class Controller {

    @FXML
    private FlowPane container ;
    @FXML
    private Label label1 ;
    @FXML
    private Label label2 ;
    // ...

    @FXML
    private Label label1000 ;

    // ...
}

I would do

<FlowPane fx:id="container" minWidth="..." minHeight="...">
</FlowPane>

and

public class Controller {

    @FXML
    private FlowPane container ;

    private List<Label> labels ;

    public void initialize() {
        labels = new ArrayList<>();
        for (int i = 1; i <= 1000; i++) {
            Label label = new Label("Label "+i);
            labels.add(label);
            container.getChildren().add(label);
        }
    }
}

As a variation on this idea, consider defining a custom component:

public class LabelFlow extends FlowPane {

    private List<Label> labels ;

    public LabelFlow(@NamedArg("numLabels") int numLabels) {
        labels = new ArrayList<>();
        for(int i = 1 ; i <= numLabels ; i++) {
            Label label = new Label("Label "+i);
            labels.add(label);
        }
        getChildren().addAll(labels);
    }

    public List<Label> getLabels() {
        return Collections.unmodifiableList(labels);
    }
}

Now in your FXML you do

<LabelFlow fx:id="labelFlow" numLabels="1000"/>

and in your controller

public class Controller {
    @FXML
    private LabelFlow labelFlow ;

    public void initialize() {
        for (Label label : labelFlow.getLabels()) {
            // do whatever you need with label....
        }
    }
}

You need to jump through a couple of hoops if you want to use a custom class like that in Scene Builder. See Adding a custom component to SceneBuilder 2.0

If you really want to define all those controls in FXML, which would be a maintenance nightmare imo, you can use reflection to access the variables. I don't recommend this, not just because it's hard to maintain, but also because reflection by its nature is error-prone (no compile-time checking) and complex.

But you could do

public class Controller {

    @FXML
    private FlowPane container ;
    @FXML
    private Label label1 ;
    @FXML
    private Label label2 ;
    // ...

    @FXML
    private Label label1000 ;

    private List<Label> labels ;

    public void initialize() throws Exception {
        labels = new ArrayList<>();
        for (int i = 1; i <= 1000; i++) {
            Field field = getClass().getDeclaredField("label"+i);
            boolean wasAccessible = field.isAccessible();
            field.setAccessible(true);
            Label label = (Label) field.get(this);
            field.setAccessible(wasAccessible);
            labels.add(label);
        }
    }
}
like image 72
James_D Avatar answered Aug 04 '26 12:08

James_D



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!