0

I've been trying button events between 2 scenes in Javafx.

This is Start.fxml (in view package):

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

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane prefHeight="292.0" prefWidth="383.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.StartController">
   <children>
      <Label fx:id="lbl1" layoutX="87.0" layoutY="60.0" prefHeight="17.0" prefWidth="209.0" />
      <TextField fx:id="txt1" layoutX="87.0" layoutY="121.0" prefHeight="25.0" prefWidth="209.0" />
      <Button fx:id="btn1" layoutX="171.0" layoutY="191.0" mnemonicParsing="false" onAction="#btn1Click" text="Click" />
   </children>
</AnchorPane>

This is Preserences.fxml (in view package):

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

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane prefHeight="292.0" prefWidth="383.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.PreferencesController">
   <children>
      <Label fx:id="lbl2" layoutX="87.0" layoutY="60.0" prefHeight="17.0" prefWidth="209.0" />
      <TextField fx:id="txt2" layoutX="87.0" layoutY="121.0" prefHeight="25.0" prefWidth="209.0" />
      <Button fx:id="btn2" layoutX="171.0" layoutY="191.0" mnemonicParsing="false" onAction="#btn2Click" text="Click" />
   </children>
</AnchorPane>

This is Main.fxml which is like a container for the previous 2 files.(in view package):

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

<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>


<AnchorPane prefHeight="481.0" prefWidth="468.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="controller.MainController">
   <children>
      <TabPane layoutX="14.0" layoutY="14.0" prefHeight="481.0" prefWidth="468.0" tabClosingPolicy="UNAVAILABLE" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
        <tabs>
          <Tab closable="false" text="Start">
               <content>
                  <fx:include source="Start.fxml" />
               </content>
          </Tab>
          <Tab closable="false" text="Preferences">
               <content>
                  <fx:include source="Preferences.fxml" />
               </content>
          </Tab>
        </tabs>
      </TabPane>
   </children>
</AnchorPane>

This is StartController.java (in controller package):

package controller;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class StartController implements Initializable {

    @FXML public static Label lbl1;
    @FXML public static TextField txt1;
    @FXML public static Button btn1;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    @FXML private void btn1Click(ActionEvent e){
        System.out.println("Button 1 clicked");
        lbl1.setText(PreferencesController.txt2.getText());
    }

}

This is PreferencesController.java (in controller package):

package controller;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class PreferencesController implements Initializable {

    @FXML public static Label lbl2;
    @FXML public static TextField txt2;
    @FXML public static Button btn2;

    @Override
    public void initialize(URL location, ResourceBundle resources) {

    }

    @FXML private void btn2Click(ActionEvent e){
        System.out.println("Button 2 clicked");
        lbl2.setText(StartController.txt1.getText());
    }

}

This is MainController.java (in controller package):

package controller;

import java.net.URL;
import java.util.ResourceBundle;

import javafx.fxml.Initializable;

public class MainController implements Initializable{

    @Override
    public void initialize(URL arg0, ResourceBundle arg1) {

    }

}

Finally, this is Main.java in application package:

package application;

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


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            Parent root = FXMLLoader.load(getClass().getResource("/view/Main.fxml"));
            Scene scene = new Scene(root);
            scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

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

But when I clicked the buttons, it gives me the errors:

"Exception in thread "JavaFX Application Thread" java.lang.RuntimeException: java.lang.reflect.InvocationTargetException...
...
Caused by: java.lang.NullPointerException
    at controller.StartController.btn1Click(StartController.java:26)
    ... 61 more"

Please help me! :(

1

1 Answer 1

2

OK so the NPE is being thrown on this line:

    lbl1.setText(PreferencesController.txt2.getText());

At the basic Java level, are only two ways that you could get that to happen:

  • when lnl1 is null, or
  • when PreferencesController.txt2 is null.

No other explanations are possible ... given that PreferencesController.txt2 is a static field.


I'm not familiar with JavaFX or FXML, but I suspect that your mistake is declaring the fields as static. I suspect that this causes the FXML mechanisms to not inject the reference to the UI component correctly. So those variables remain as null ... and you get an NPE.

Confirmation is here: https://stackoverflow.com/a/23109125/139985. (Thanks for the link @James_D)

Sign up to request clarification or add additional context in comments.

2 Comments

upvoted because it is the correct answer. Its not possible to inject FXML static fields.
Thanks for the confirmation (and the vote, though that's less important).

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.