javafxscenebuilderpanehbox

More efficient way to add Panes to an HBox?


I am working on a project that is going to involve adding panes (or hboxes if that works better) to a very wide HBox. I set it up in an fxml pretty easily but I'm already going to have to make a few of these and I would love to avoid all the copying pasting. So I figured I should try and use a for loop to populate the HBox but for whatever reason it is not working. I'm in the very beginning steps so my code is very simple and straight forward.

This is the basic sample I'm trying to recreate

<HBox>
   <children>
      <Pane fx:id="pane0" prefHeight="200.0" prefWidth="200.0">
         <children>
            <Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
         </children></Pane>
      <Pane fx:id="pane1" prefHeight="200.0" prefWidth="200.0">
         <children>
            <Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
         </children></Pane>
      <Pane fx:id="pane2" prefHeight="200.0" prefWidth="200.0">
         <children>
            <Button layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
         </children></Pane>
   </children>
</HBox>

So to create it dynamically (and for clarity) I created a class for the HBox and the panes. For now each pane just has a button but they will undergo further customization once this code works. Same with the HBox.

Here's the HBox

public class HBoxTestClass {

    @FXML
    HBox hBox = new HBox();

    public HBoxTestClass(){

    }
    @FXML
    public void initialize(){
        populateHBox();
    }
    private void populateHBox(){
        for (int i = 0; i < 3; i++){
            hBox.getChildren().add(new TestPane());
            hBox.setSpacing(10);
        }
    }
}

its fxml

<HBox fx:id="hBox" xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="sample.HBoxTestClass"
            prefHeight="400.0" prefWidth="600.0">

</HBox>

The pane class and its fxml

public class TestPane extends Pane{

    @FXML Pane testPane = new Pane();
    @FXML Button button = new Button();

    public TestPane(){

    }
    @FXML
    private void initialize(){
        button.setText("Click Me!");
    }
}
<Pane fx:id="testPane" xmlns="http://javafx.com/javafx"
            xmlns:fx="http://javafx.com/fxml"
            fx:controller="sample.TestPane"
            prefHeight="200.0" prefWidth="200.0">
    <children>
        <Button fx:id="button" layoutX="71.0" layoutY="95.0" mnemonicParsing="false" text="Button" />
    </children>

</Pane>

So my very simple code above just produces a blank, wide screen with no panels in it. I put a console print in the constructor of my TestPane class so I know it's getting called but still nothing appears. Any advice? Thanks


Solution

  • I am not sure what you are doing in your code incorrectly. Code like @FXML Pane testPane = new Pane(); should look like @FXML Pane testPane;. I am not sure how code like @FXML public void initialize(){ is being called in your program. Try to follow this MCVE.

    Main

    import javafx.application.Application;
    import javafx.fxml.FXMLLoader;
    import javafx.scene.Parent;
    import javafx.scene.Scene;
    import javafx.stage.Stage;
    
    /**
     *
     * @author blj0011
     */
    public class JavaFXApplication363 extends Application
    {
    
        @Override
        public void start(Stage stage) throws Exception
        {
            Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
    
            Scene scene = new Scene(root);
    
            stage.setScene(scene);
            stage.show();
        }
    
        /**
         * @param args the command line arguments
         */
        public static void main(String[] args)
        {
            launch(args);
        }
    
    }
    

    Controller

    import java.net.URL;
    import java.util.ResourceBundle;
    import javafx.fxml.FXML;
    import javafx.fxml.Initializable;
    import javafx.scene.control.Label;
    import javafx.scene.layout.HBox;
    import javafx.scene.layout.StackPane;
    
    /**
     *
     * @author blj0011
     */
    public class FXMLDocumentController implements Initializable
    {
    
        @FXML
        private HBox hBox;
    
        @Override
        public void initialize(URL url, ResourceBundle rb)
        {
            // TODO
            for (int i = 0; i < 5; i++) {
                StackPane stackPane = new StackPane(new Label("Label: " + i));
                hBox.getChildren().add(stackPane);
            }
        }
    
    }
    

    FXML

    <?xml version="1.0" encoding="UTF-8"?>
    
    <?import javafx.scene.layout.HBox?>
    
    
    <HBox fx:id="hBox" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication363.FXMLDocumentController" />