0

Still relatively new to JavaFX and I'm having a bit of trouble getting buttons to add to a GUI that I've setup.

I have 3 files: Main.java, Controller.java, and sample.fxml (each located below)

From what I've read via tutorials and docs, the Controller.java file is loaded and linked to the fxml file due to the "fx:controller" section -- but beyond that I cannot properly get the program to run that method.

I've tried setting up the Main.java to be the controller and just fusing the code in that way (bombed). Even actively went against the form and trying creating a new instance of the Controller.java in the Main.java file (which would essentially just be creating another instance alongside of what's loaded when the program runs) and that too bombed.

Any pointers?

Main.java

package soundboardEoZ;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class Main extends Application {

    int sound_index = 1;
    int target = 10;

    @Override
    public void start(Stage primaryStage) throws Exception{

        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();


        while (sound_index < target){
            // This is where I want to call the addButton() method from Controller.java
            sound_index++;
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Controller.java

package soundboardEoZ;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;

public class Controller {
    int index = 2;
    int target = 10;

    @FXML
    GridPane button_grid;

    void test(){
        System.out.println("Testing");
    }

    void addButton(){
        Button sound_button = new Button("Button_" + index);
        button_grid.add(sound_button, index,2);
    }

}

And our FXML file

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Menu?>
<?import javafx.scene.control.MenuBar?>
<?import javafx.scene.control.MenuItem?>
<?import javafx.scene.control.SeparatorMenuItem?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Text?>

<!--VBox is a single column panel-->

<?import javafx.scene.text.Font?>
<VBox id="vbox" prefHeight="400" prefWidth="1000" xmlns="http://javafx.com/javafx/8.0.76-ea" xmlns:fx="http://javafx.com/fxml/1" fx:controller="soundboardEoZ.Controller">
    <MenuBar fx:id="menuBar"> <!--Literally a MenuBar-->
        <menus> <!--Holds the menu concept for the bar-->
            <Menu text="File"> <!--Menu holds Items-->
                <items>
                    <MenuItem text="New" />
                    <MenuItem text="Open" />
                    <SeparatorMenuItem />
                    <MenuItem text="Save Settings" />
                    <SeparatorMenuItem />
                    <MenuItem text="Settings" />
                </items>
            </Menu>
            <Menu text="Edit">
                <items>
                    <MenuItem text="Copy" />
                </items>
            </Menu>
            <Menu text="About">
                <items>
                    <MenuItem text="Team" />
                </items>
            </Menu>
            <Menu text="Help">
                <items>
                    <MenuItem text="Guide" />
                    <MenuItem text="Forums" />
                </items>
            </Menu>
        </menus>
    </MenuBar>

    <Pane>
        <GridPane>
            <Button GridPane.columnIndex="0">I'm another Test</Button>
            <Text fill="RED" stroke="BLACK" strokeWidth="2.0" GridPane.columnIndex="1">
                <font><Font size="25"/></font>
                Testing
            </Text>
        </GridPane>
    </Pane>

    <GridPane fx:id="button_grid" hgap="10" vgap="10" xmlns:fx="http://javafx.com/fxml">

        <!--<Button GridPane.columnIndex="0" GridPane.rowIndex="1">Hello!</Button>-->

        <!--<Button GridPane.columnIndex="1">Hiya!</Button>-->

        <!--<Text text="Clickity!" GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="2" />-->

        <!--<Label text="Configuration Name:" GridPane.columnIndex="0" GridPane.rowIndex="1" />-->
        <!--<TextField GridPane.columnIndex="1" GridPane.rowIndex="1" />-->

        <!--<Button fx:id="test_button" text="Hello"></Button>-->

    </GridPane>
</VBox>
1
  • Why do you want to call that code from Main? Just define an initialize() method in the controller and call it from there. Commented Oct 17, 2016 at 23:21

1 Answer 1

2

The Application subclass - Main in your example - is really supposed to just startup the application. I.e. it should load the FXML, put it in a window, and show the window. Initialization and other configuration of the UI defined by the FXML, along with event handling, should be done by the controller. So you are not really trying to execute this code from the correct place. You should just do this from the controller:

package soundboardEoZ;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;

public class Controller {
    int index ;
    int target = 10;

    @FXML
    GridPane button_grid;

    public void initialize() {
        for (index = 2; index < target ; index++) {
            addButton();
        }
    }

    public void test(){
        System.out.println("Testing");
    }

    public void addButton(){
        Button sound_button = new Button("Button_" + index);
        button_grid.add(sound_button, index,2);
    }

}

and then remove all that functionality from Main:

package soundboardEoZ;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception{

        Parent root = FXMLLoader.load(getClass().getResource("sample.fxml"));
        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();


    }

    public static void main(String[] args) {
        launch(args);
    }
}

If you really want to call that method from Main (but again, I can't emphasize enough that this is really using the toolkit in a way contrary to the patterns around which it was designed), create an FXMLLoader instance and get the controller from it. You'll need the controller to track the index properly:

package soundboardEoZ;

import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;

public class Controller {
    int index = 2;

    @FXML
    GridPane button_grid;

    public void test(){
        System.out.println("Testing");
    }

    public void addButton(){
        Button sound_button = new Button("Button_" + index);
        button_grid.add(sound_button, index,2);
        index++;
    }

}

and then you could do:

package soundboardEoZ;

import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.stage.Stage;

public class Main extends Application {

    int sound_index = 1;
    int target = 10;

    @Override
    public void start(Stage primaryStage) throws Exception{

        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml"));
        Parent root = loader.load();

        primaryStage.setTitle("Hello World");
        primaryStage.setScene(new Scene(root, 300, 275));
        primaryStage.show();

        Controller controller = loader.getController();

        while (sound_index < target){
            controller.addButton();
            sound_index++;
        }
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

AH! Thank you, going through documentation and various other sources I kept finding "StartUp" methods being called the initializer. Will test this later tonight, thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.