在设置 fx:id 后访问字段时在 javaFX 中出现空指针异常

问题描述 投票:0回答:0

这是按钮的 fxml 标记:

<Button fx:id="btn" layoutX="279.0" layoutY="130.0" mnemonicParsing="false" text="Button" />

舞台运行良好,但我不能使用任何字段,在这种情况下,btn。这就是我加载它的方式:

            FXMLLoader loader = new FXMLLoader(getClass().getResource("Sample.fxml"));

            root = loader.load();
            btn.setOnAction(x -> {
            System.out.println("button clicked");   
            });

字段声明如下:

    @FXML 
    Button btn;

来自堆栈跟踪的消息

java.lang.NullPointerException:无法调用“javafx.scene.control.Button.setOnAction(javafx.event.EventHandler)”,因为“this.btn”为空 在 FxmlTest/application.Main.start(Main.java:29)

(Main.java:29 us btn.setOnAction...)

最后,我这样设置控制器:

<AnchorPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" **fx:controller="application.Main"**>

我试过的解决方案

  1. 使控制器类成为主类。
  2. 从 Platform.runLater(...) 访问字段
  3. 在加载根之前访问该字段。
 root = loader.load();
  1. 在没有 Maven 的情况下创建了一个完整的模块化项目,因为我认为问题可能是由 Maven 引起的。例如,getResources() 仅适用于 Maven 项目中的“/”,我的项目就是这样。

注意事项

  1. 我读到有人建议实施 initialize() 但我认为这是现在直接注入的旧做法(?)。
  2. 这绝对感觉像是一个错误或其他什么,因为使用 SceneBuilder,我注意到在我用记事本打开 fxml 文件然后关闭它之前,我的 IDE 没有获取保存的更改。

*完整代码

package application;
    
import javafx.application.Application;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.AnchorPane;
import javafx.stage.Stage;


public class Main extends Application {
    
    @FXML
    AnchorPane root;
    
    @FXML
    Label basmalaLbl;
    
    @FXML 
    Button btn;
    @Override
    public void start(Stage primaryStage) {
        try {
            FXMLLoader loader = new FXMLLoader(getClass().getResource("Sample.fxml"));

            root = loader.load();
            btn.setOnAction(x -> {
            System.out.println("button clicked");   
            });
            
            Scene scene = new Scene(root,400,400);
            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);
    }
}

FXML

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Font?>

<AnchorPane fx:id="root" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.Main">
   <children>
      <Label fx:id="basmalaLbl" layoutX="272.0" layoutY="192.0" text="بسم الله!">
         <font>
            <Font size="33.0" />
         </font>
      </Label>
      <Button id="btn" fx:id="btn" layoutX="279.0" layoutY="130.0" mnemonicParsing="false" text="Button" />
   </children>
</AnchorPane>
javafx fxml
© www.soinside.com 2019 - 2024. All rights reserved.