0
votes

I load the FXML1 in the start method and when the Button is clicked i open up the FXML2. Here's my question: can I change the text of the Label "label" when the button is pressed?

Main:

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class FXMLExample extends Application {

@Override
public void start(Stage primaryStage) throws Exception {
    Parent root = FXMLLoader.load(getClass().getResource("FXML1.fxml"));
    Scene scene = new Scene(root);
    primaryStage.setScene(scene);
    primaryStage.show();
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

}

Controller: in the initialize method is the comment: label.setText("Hello World"); If I uncomment it and try it i get an Exception.

package fxmlexample;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.stage.Stage;

/**
* FXML Controller class
*/
public class FXMLController implements Initializable {

@FXML
Button button;
@FXML
Label label;

public void pressButton(ActionEvent event) throws Exception {
    if (event.getSource() == button) {
        Parent root = FXMLLoader.load(getClass().getResource("FXML2.fxml"));
        Scene scene = new Scene(root);
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.show();
    }
}

/**
 * Initializes the controller class.
 *
 * @param url
 * @param rb
 */
@Override
public void initialize(URL url, ResourceBundle rb) {
    //   label.setText("Hello World");
}

}

FXML1:

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.Pane?>

<Pane 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="fxmlexample.FXMLController">
<children>
     <Button fx:id="button" layoutX="264.0" layoutY="185.0" mnemonicParsing="false" onAction="#pressButton" prefHeight="31.0" prefWidth="73.0" text="Click me!" />
</children>
</Pane>

FXML2:

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

 <?import javafx.scene.control.Label?>
 <?import javafx.scene.layout.Pane?>

 <Pane prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8.0.141" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fxmlexample.FXMLController">
   <children>
       <Label fx:id="label" layoutX="244.0" layoutY="177.0" prefHeight="46.0" prefWidth="112.0" style="-fx-background-color: lime;" />
   </children>
 </Pane>
1
I guess "changing a fxml" means modifying the scene created from the fxml, not the fxml file itself? This is of course possible, but there seem to be some pitfalls that cause confusion for serveral users, e.g. creating a new controller instance to communicate with another one created by FXMLLoader or loading the fxml multiple times and trying to manipulate a previously loaded scene using the new one... Please create a minimal reproducible example. This would make it far easier to come up with a recommendatio instead of simply answering "Yes". - fabian
Yeah modifying the scene. And I'm trying to do an example. @fabian - Victor

1 Answers

0
votes

The label is only initialized in the controller for FXML2 (because that FXML file has an element with fx:id="label"). The initialize() method is called on both the controllers. Consequently, when initialize() is called on the controller for FXML1, label is null and you get a null pointer exception.

Use a different controller class for each of the FXML files:

package fxmlexample;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.stage.Stage;

/**
* FXML Controller class
*/
public class FXMLController1 implements Initializable {

    @FXML
    Button button;
    public void pressButton(ActionEvent event) throws Exception {

        Parent root = FXMLLoader.load(getClass().getResource("FXML2.fxml"));
        Scene scene = new Scene(root);
        Stage stage = new Stage();
        stage.setScene(scene);
        stage.show();

    }

    /**
     * Initializes the controller class.
     *
     * @param url
     * @param rb
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {

    }

}

and

package fxmlexample;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Label;

/**
* FXML Controller class
*/
public class FXMLController2 implements Initializable {

    @FXML
    Label label;



    /**
     * Initializes the controller class.
     *
     * @param url
     * @param rb
     */
    @Override
    public void initialize(URL url, ResourceBundle rb) {
           label.setText("Hello World");
    }

}

Finally, modify the fx:controller attribute in each FXML file to point to the correct class.