how to access a deeply nested button in JAVAFX/FXML

Kamper K :

as seen in this FXML Hierarchy:

enter image description here

I have :

  • 1 stack pane which contains 6 Accordions
  • Accordions have fx:id's
  • each accordion has from 1 to sometimes 3 Titled panes
  • each Titled pane has 1 TilePane
  • TilePanes contain Buttons.

Now , in the controller class i have a reference to the parent stackpane:

@FXML
    private StackPane stackpaneOfCategories;

and it's children, the Accordions :

ObservableList<Node> stackpaneAccordionsList = stackpaneOfCategories.getChildren();

now after seeing the hierarchy i want to give every single button a .setOnAction when they are clicked,i tried doing that by giving id's all around , but i soon realized that it's not an optimal solution.

how can i set an OnAction for the buttons nested deep in my StackPane of Accordions ?

EDIT : this is the FXML code :

   <?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Accordion?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TitledPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.layout.TilePane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>

<GridPane alignment="CENTER" hgap="10.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="600.0" prefWidth="900.0" stylesheets="@style.css" vgap="10.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="sample.Lancer">
  <columnConstraints>
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
      <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
    <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
    <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
  </columnConstraints>
  <rowConstraints>
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
      <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
    <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
  </rowConstraints>
   <children>
      <Button maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Payement" textAlignment="CENTER" wrapText="true" GridPane.columnSpan="2" />
      <StackPane fx:id="stackpaneOfCategories" prefHeight="150.0" prefWidth="200.0" GridPane.columnIndex="3" GridPane.columnSpan="6" GridPane.rowIndex="2" GridPane.rowSpan="6">
         <children>
            <Accordion fx:id="categorieBoisson">
              <panes>
                <TitledPane animated="false" text="Boissons Chaudes + Eau">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Eau 1L" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Cappuccino" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="105.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Latté" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="190.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Americano" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Espresso" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                </TitledPane>
                <TitledPane animated="false" text="Canettes">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Coca Cola 33 CL" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Pepsi 33 CL" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="105.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Eau 33CL" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                </TitledPane>
                <TitledPane animated="false" text="Gazeuses 1L">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Sprite" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Hamoud Boualem" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="105.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Miranda" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                </TitledPane>
              </panes>
            </Accordion>
            <Accordion fx:id="categorieBurger">
              <panes>
                <TitledPane animated="false" text="Burger M">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Chicken Burger" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Mexican Burger" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                </TitledPane>
                <TitledPane animated="false" text="Burger L">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Chicken Burger" textAlignment="CENTER" wrapText="true" />
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Mexican Burger" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                </TitledPane>
              </panes>
            </Accordion>
            <Accordion fx:id="categorieTacos" layoutX="10.0" layoutY="10.0">
               <panes>
                  <TitledPane animated="false" layoutX="10.0" layoutY="452.0" text="Tacos L">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Poulet a l'ail" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Poulet Special" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="105.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Foie" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="190.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Mexicano" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                  </TitledPane>
                  <TitledPane animated="false" layoutX="10.0" layoutY="452.0" text="Tacos XL">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Poulet a l'ail" textAlignment="CENTER" wrapText="true" />
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Poulet Special" textAlignment="CENTER" wrapText="true" />
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Foie" textAlignment="CENTER" wrapText="true" />
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Mexicano" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                  </TitledPane>
               </panes>
            </Accordion>
            <Accordion fx:id="categoriePizza" layoutX="10.0" layoutY="10.0">
               <panes>
                  <TitledPane animated="false" layoutX="10.0" layoutY="452.0" text="Pizza M">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Margarita" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Vegetarienne" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="105.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Mexican" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="190.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Océan" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="275.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Chicken" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="360.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="4 Cheeses" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="445.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="444 Special" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                  </TitledPane>
               </panes>
            </Accordion>
            <Accordion fx:id="categorieBaguette" layoutX="10.0" layoutY="10.0">
               <panes>
                  <TitledPane animated="false" layoutX="10.0" layoutY="452.0" text="Baguettes Farcies M">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Poulet" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Viande Hachée" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="105.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Thon" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="190.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="4 Cheeses" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                  </TitledPane>
               </panes>
            </Accordion>
            <Accordion fx:id="categorieSouflee" layoutX="10.0" layoutY="10.0">
               <panes>
                  <TitledPane animated="false" layoutX="10.0" layoutY="452.0" text="Souflés M">
                     <content>
                        <TilePane hgap="5.0" prefHeight="200.0" prefWidth="200.0" vgap="5.0">
                           <children>
                              <Button mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Poulet" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="20.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Viande Hachée" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="105.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="Thon" textAlignment="CENTER" wrapText="true" />
                              <Button layoutX="190.0" layoutY="20.0" mnemonicParsing="false" prefHeight="80.0" prefWidth="80.0" text="4 Cheeses" textAlignment="CENTER" wrapText="true" />
                           </children>
                        </TilePane>
                     </content>
                  </TitledPane>
               </panes>
            </Accordion>
         </children>
      </StackPane>
      <Button layoutX="10.0" layoutY="10.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#backto_commandes" text="Annuler" textAlignment="CENTER" wrapText="true" GridPane.rowIndex="8" />
      <Button layoutX="10.0" layoutY="544.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Supprimer" textAlignment="CENTER" wrapText="true" GridPane.columnIndex="1" GridPane.rowIndex="8" />
      <Button layoutX="98.0" layoutY="544.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Imprimer" textAlignment="CENTER" wrapText="true" GridPane.columnIndex="7" GridPane.rowIndex="8" />
      <Button layoutX="632.0" layoutY="544.0" maxHeight="1.7976931348623157E308" maxWidth="1.7976931348623157E308" mnemonicParsing="false" text="Envoyer" textAlignment="CENTER" wrapText="true" GridPane.columnIndex="8" GridPane.rowIndex="8" />
      <Text strokeType="OUTSIDE" strokeWidth="0.0" text="2500.00" GridPane.columnIndex="1" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="CENTER" />
      <Text layoutX="174.0" layoutY="519.0" strokeType="OUTSIDE" strokeWidth="0.0" text="NET TOTAL :" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="CENTER" />
      <Text layoutX="166.0" layoutY="519.0" strokeType="OUTSIDE" strokeWidth="0.0" text="DA" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="7" GridPane.valignment="CENTER" />
      <VBox alignment="TOP_RIGHT" GridPane.columnIndex="2" GridPane.halignment="CENTER" GridPane.rowIndex="1" GridPane.valignment="CENTER">
         <children>
            <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Table : 12" />
            <Text strokeType="OUTSIDE" strokeWidth="0.0" text="Couverts : 4" />
         </children>
      </VBox>
      <VBox GridPane.rowIndex="1">
         <children>
            <Text strokeType="OUTSIDE" strokeWidth="0.0" text="N° 59924" />
            <Text strokeType="OUTSIDE" strokeWidth="0.0" text="ID: H.AbdAllah N°5482187" />
         </children>
      </VBox>
      <VBox alignment="BOTTOM_CENTER" GridPane.columnIndex="1" GridPane.rowIndex="1">
         <children>
            <Text strokeType="OUTSIDE" strokeWidth="0.0" text="2 Mars 2020 21:46" />
         </children>
      </VBox>
      <TableView prefHeight="200.0" prefWidth="200.0" GridPane.columnSpan="3" GridPane.rowIndex="2" GridPane.rowSpan="5">
        <columns>
          <TableColumn prefWidth="58.0" text="Quantité" />
          <TableColumn prefWidth="181.0" text="Nom Article" />
            <TableColumn minWidth="0.0" prefWidth="53.0" text="Prix" />
        </columns>
      </TableView>
      <ScrollPane fitToHeight="true" GridPane.columnIndex="3" GridPane.columnSpan="6" GridPane.halignment="CENTER" GridPane.rowSpan="2" GridPane.valignment="CENTER">
         <content>
            <HBox fx:id="hboxOfCategories" alignment="CENTER_LEFT" spacing="10.0">
               <children>
                  <Button maxHeight="1.7976931348623157E308" mnemonicParsing="false" prefHeight="57.0" prefWidth="82.0" text="Boissons" />
                  <Button layoutX="10.0" layoutY="10.0" maxHeight="1.7976931348623157E308" mnemonicParsing="false" prefHeight="57.0" prefWidth="82.0" text="Burger" />
                  <Button layoutX="102.0" layoutY="10.0" maxHeight="1.7976931348623157E308" mnemonicParsing="false" prefHeight="57.0" prefWidth="82.0" text="Tacos" />
                  <Button layoutX="378.0" layoutY="10.0" maxHeight="1.7976931348623157E308" mnemonicParsing="false" prefHeight="57.0" prefWidth="82.0" text="Pizza" />
                  <Button layoutX="194.0" layoutY="10.0" maxHeight="1.7976931348623157E308" mnemonicParsing="false" prefHeight="57.0" prefWidth="82.0" text="Baguette Farcie" textAlignment="CENTER" wrapText="true" />
                  <Button layoutX="286.0" layoutY="10.0" maxHeight="1.7976931348623157E308" mnemonicParsing="false" prefHeight="57.0" prefWidth="82.0" text="Souflee" />
               </children>
            </HBox>
         </content>
      </ScrollPane>
   </children>
</GridPane>
adxl :

At first this will look kind of complex, but read it carefully and it will become clear.

Basically, starting from the StackPane, it will go deep into the structure "recursively" using the previous result (which is a Set of Nodes) with forEach. Until getting to the buttons and then setting their OnAction event handler.

stackpaneOfCategories.getChildren()
                .forEach(accordion->((Accordion)accordion).getPanes()
                .forEach(tilePane->((TilePane)((tilePane).getContent())).getChildren()
                .forEach(button->((Button)button)
                                         .setOnAction(a->System.out.println(((Button)button).getText())))));

The disadvantage of this method is that it sets the same OnAction for all the buttons, if you want different behavior for each button, I guess you have no other choice than setting them using fx:ids (but I may be wrong).

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=277577&siteId=1