Javant
Javant

Reputation: 1019

How to separate my gui in javafx?

Usually when I create my gui I use swing and create my own class extending jframe. Then I create a controller class and base my program on mvc design. But I decided to try out javafx recently and I'm a bit lost.

Currently I just have my all of my gui in my main class on the start method, where all used and referenced objects are declared as fields in my main class. This looks very messy and not so rightly implemented. Is there anyway to do what I was previously doing with swing, with javafx?

Upvotes: 1

Views: 2795

Answers (2)

Javant
Javant

Reputation: 1019

Solution: Create a class that extends Scene that takes stage as param. Move everything that would be in main into start. Which allows the regular swing mvc design.

public class Main extends Application {

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

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

        CardModel model = new CardModel();
        CardView scene = new CardView(stage);       
        CardController controller= new CardController(model,scene);

        stage.setTitle("Title");
        stage.setMaximized(true);
        stage.setMinWidth(500);
        stage.setMinHeight(550);
        stage.setScene(scene);
        stage.show();
    }

}

Upvotes: 1

Westranger
Westranger

Reputation: 1367

In general you you have a main class which justs starts you GUI. The View part of you MVC is handle by an XML file (called FXML). This FXML is connected to an controller class. JavaFX also allows you to directly injects all GUI components into an proper variable inside of the controller, so you don't need to look them up. The easiest way to get an example project is using maven archetypes for JavaFX:

mvn archetype:generate -DarchetypeGroupId=com.zenjava -DarchetypeArtifactId=javafx-basic-archetype

Just go to an directory where you project should be an type the above command. It then directly generates an example projects for you. So lets start with the main class

public class MainApp extends Application {

    private static final Logger log = LoggerFactory.getLogger(MainApp.class);

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

    public void start(Stage stage) throws Exception {

        log.info("Starting Hello JavaFX and Maven demonstration application");

        String fxmlFile = "/fxml/hello.fxml";
        log.debug("Loading FXML for main view from: {}", fxmlFile);
        FXMLLoader loader = new FXMLLoader();
        Parent rootNode = (Parent) loader.load(getClass().getResourceAsStream(fxmlFile));

        log.debug("Showing JFX scene");
        Scene scene = new Scene(rootNode, 400, 200);
        scene.getStylesheets().add("/styles/styles.css");

        stage.setTitle("Hello JavaFX and Maven");
        stage.setScene(scene);
        stage.show();
    }
}

As you can see it just loads the the FXMl and displays the main window. The FXML specifies the visual structure of your GUI (labels, textfields, images, buttons scroll bars etc)

<MigPane id="rootPane" fx:controller="example.HelloController" styleClass="main-panel" layout="insets 20" cols="[label, pref!][grow, 50::]" rows="" xmlns:fx="http://javafx.com/fxml">
    <Label text="First Name:" />
    <TextField fx:id="firstNameField" prefColumnCount="30" MigPane.cc="growx, wrap" />
    <Label text="Last Name:" /> <TextField fx:id="lastNameField" prefColumnCount="30" MigPane.cc="growx, wrap" />
    <Button text="Say Hello" onAction="#sayHello" MigPane.cc="skip, gap :push, gaptop 15, wrap" />
    <Label fx:id="messageLabel" styleClass="hello-message" MigPane.cc="span, growx, gaptop 15" />
</MigPane >

The Controller which is used to separate the GUI from its logic is specified int the FXML and the fx:id is used to injects the element directly into the proper variable inside of the controller

public class HelloController
{
    private static final Logger log = LoggerFactory.getLogger(HelloController.class);

    @FXML private TextField firstNameField;
    @FXML private TextField lastNameField;
    @FXML private Label messageLabel;

    public void sayHello() {

        String firstName = firstNameField.getText();
        String lastName = lastNameField.getText();

        StringBuilder builder = new StringBuilder();

        if (!StringUtils.isEmpty(firstName)) {
            builder.append(firstName);
        }

        if (!StringUtils.isEmpty(lastName)) {
            if (builder.length() > 0) {
                builder.append(" ");
            }
            builder.append(lastName);
        }

        if (builder.length() > 0) {
            String name = builder.toString();
            log.debug("Saying hello to " + name);
            messageLabel.setText("Hello " + name);
        } else {
            log.debug("Neither first name nor last name was set, saying hello to anonymous person");
            messageLabel.setText("Hello mysterious person");
        }
    }

}

The controller has fields with an @FXML annotation those are injected GUI elements. As you can the the variable name equals the fx:id this is necessary in order for JavaFX to injects the elements. For creating the FXML you can use the Oracle Scene Builder or the on from Gluon both are very easy to use and allow you to quickly generate an nice looking GUI.

Upvotes: 1

Related Questions