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! :(

fabian
  • 80,457
  • 12
  • 86
  • 114
Yin
  • 395
  • 4
  • 6
  • 16
  • 1
    You can't declare `@FXML`-injected fields as static. See http://stackoverflow.com/questions/23105433/javafx-8-compatibility-issues-fxml-static-fields/23109125#23109125 – James_D Feb 08 '15 at 04:50

1 Answers1

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)

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216