4

I need 15 buttons in my application but I dont want to declare them one by one like

@FXML
private Button button1;
@FXML
private Button button2;
@FXML
private Button button3;
...
...
...
...

Instead, I want to this, create a array of buttons.

@FXML
private Button[][] button = new Button[5][3];

However, In the scene builder, there is only one button that I can choose and I think it reference to the array not the single button element. Is there any way that I can easily make this work?

Neo Yang
  • 111
  • 2
  • 7

2 Answers2

3

Note that is possible to store the data in a ArrayList as GoXR3Plus described in his answer. However you cannot create an array in fxml. To do this you'd need create the array from java code (e.g. in the initialize method) and attach some information to the Node that allows you to retrieve the index information.

This could e.g. be done by using a static helper method to attach information as well as a css class selector to the nodes, and inject a common ancestor of these nodes to the controller:

<VBox fx:id="root" prefHeight="400.0" prefWidth="600.0" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxml.arraystore.StoreController">
    <children>
        <Button text="1" Helper.indices="0 0"/>
        <Button text="2" Helper.indices="0 1"/>
        <Button text="3" Helper.indices="1 1"/>
        <Button text="4" Helper.indices="1 0"/>
        <Button text="5" Helper.indices="2 0"/>
        <Button text="6" Helper.indices="2 1"/>
    </children>
</VBox>

Helper

public class Helper {

    private static final String MARK_CLASS = "array-store-mark";
    private static final String MARK_CLASS_SELECTOR = "." + MARK_CLASS;
    private static final String INDICES_KEY = "arrayStoreIndices";

    public static void setIndices(Node node, String indices) {
        if (node == null || indices == null) {
            throw new IllegalArgumentException();
        }
        String[] parts = indices.split("\\s+");
        int[] is = new int[]{Integer.parseInt(parts[0]), Integer.parseInt(parts[1])};

        // add css class
        node.getStyleClass().add(MARK_CLASS);

        // add index data
        node.getProperties().put(INDICES_KEY, is);
    }

    public static <T extends Node> T[][] getAsArray(Node parent, Class<T> nodeClass) {
        if (parent == null) {
            throw new IllegalArgumentException();
        }
        int max1 = 0;
        int max2 = 0;

        // find nodes by class
        Set<Node> marked = parent.lookupAll(MARK_CLASS_SELECTOR);

        // find array size
        for (Node n : marked) {
            n.getStyleClass().remove(MARK_CLASS);
            if (nodeClass.isAssignableFrom(n.getClass())) {
                int[] is = (int[]) n.getProperties().get(INDICES_KEY);
                if (max1 < is[0]) {
                    max1 = is[0];
                }
                if (max2 < is[1]) {
                    max2 = is[1];
                }
            }
        }

        T[][] result = (T[][]) Array.newInstance(nodeClass, max1+1, max2+1);

        // put data in array
        for (Node n : marked) {
            int[] is = (int[]) n.getProperties().remove(INDICES_KEY);

            if (nodeClass.isAssignableFrom(n.getClass())) {
                result[is[0]][is[1]] = (T) n;
            }
        }

        return result;
    }

}

Controller class

public class StoreController {

    // common parent
    @FXML
    private Parent root;

    private Button[][] buttons;

    @FXML
    private void initialize() {
        buttons = Helper.getAsArray(root, Button.class);
        System.out.println(Arrays.deepToString(buttons));
    }

}
fabian
  • 80,457
  • 12
  • 86
  • 114
  • Thank you so much! It is like a next level solution that I probably didn't get it. I will study your code so hard! – Neo Yang Nov 03 '16 at 23:35
1

I assume that you can only modify it by playing with the code of the fxml file.

For a simple ArrayList you can do the below(check fx:define and fx:reference):

First way->1

        <fx:define>
          <!-- create buttons and store them in a list -->
           <ArrayList fx:id="buttonsArray">
              <Button fx:id="firstButton" />
              <Button fx:id="secondButton" />
              <Button fx:id="thirdButton" />
           </ArrayList>
        </fx:define>


        <!-- add buttons in the list to scene graph -->
        <fx:reference source="firstButton"/>
        <fx:reference source="secondButton"/>
        <fx:reference source="thirdButton"/>

Second way->2

        <!-- add buttons in the list to scene graph -->
         <Button fx:id="firstButton" />
         <Button fx:id="secondButton" />
         <Button fx:id="thirdButton" />

       <fx:define>
          <!--store them into a list -->
           <ArrayList fx:id="buttonsArray">
               <fx:reference source="firstButton"/>
               <fx:reference source="secondButton"/>
               <fx:reference source="thirdButton"/>
           </ArrayList>
        </fx:define>

About a multi dimensional ArrayList[ 3 ][ 2 ] Using the first way->1 it must be something like:

       <fx:define>
          <!-- create buttons and store them in a list -->
           <ArrayList fx:id="array">
              <Button fx:id="Button_0_0" /> //first row , first column
              <Button fx:id="Button_0_1" />
              <Button fx:id="Button_0_2" />
              <ArrayList fx:id="buttonsArray">
                  <Button fx:id="Button_1_0" /> //second row , first column
                  <Button fx:id="Button_1_1" />
                  <Button fx:id="Button_1_2" />
              </ArrayList>
           </ArrayList>
        </fx:define>


         <!-- add buttons in the list to scene graph -->
         <fx:reference source="Button_0_0" />
         <fx:reference source="Button_0_1" />
         <fx:reference source="Button_0_2" />
         <fx:reference source="Button_1_0" />
         <fx:reference source="Button_1_1" />
         <fx:reference source="Button_1_2" />

I reccomend you read all the links given above and also:

1)create array of Label using FXML in JavaFX

2)Grouping together JavaFX FXML Objects

Community
  • 1
  • 1
GOXR3PLUS
  • 6,877
  • 9
  • 44
  • 93