【问题标题】:JavaFX, Label null pointer exceptionJavaFX,标签空指针异常
【发布时间】:2016-07-11 06:13:54
【问题描述】:

我目前正在编写的程序遇到以下问题,我在互联网上进行了搜索,但我真的找不到任何东西可以帮助我理解以下问题

所以在另一个类中,我编写了一个方法,每当单击搜索按钮时都会执行此方法,该方法如下所示:

public void searchButton(){
        try {
            new SearchController().display();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

然后 SearchController 类看起来像这样(我在这里简化了它):

public class SearchController {

    @FXML
    private Button cancelButton;

    @FXML
    private Label what;

    private static Stage stage;

    private static BorderPane borderPane;

    @FXML
    public void initialize(){
        what.setText("Testing"); // this woks
        cancelButton.setOnAction(e -> stage.close());
    }

    public void display() throws IOException {

        stage = new Stage();
        stage.setResizable(false);
        stage.setTitle("Product search");
        stage.initModality(Modality.APPLICATION_MODAL);
        FXMLLoader loader = new FXMLLoader();
        loader.setLocation(SearchController.class.getResource("Search.fxml"));
        borderPane = loader.load();
        Scene scene = new Scene(borderPane);
        stage.setScene(scene);
        //what.setText("Testing") and this doesn't work
        stage.showAndWait();

    }



}

有人可以告诉我为什么可以在初始化方法上写文本(该方法在borderPane = loader.load(); 行之后被调用......那么如果我尝试在之后写在标签上为什么它不起作用行?)

提前谢谢你

【问题讨论】:

  • 顺便说一句,请注意,如果您最终加载 FXML 文件两次(并同时显示两者),您的 static 字段将是一场灾难。你根本不需要这些,它们是等待发生的错误。您可以使用cancelButton.setOnAction(e -> cancelButton.getScene().getWindow().hide()); 关闭窗口(并去掉stage 字段。如果您确实需要borderPane 字段,请将其设为实例变量并从fxml 文件中注入(即删除static 和只需将 fx:id="borderPane" 放在 fxml 的根元素上)。

标签: javafx nullpointerexception label


【解决方案1】:

FXMLLoader 创建在 FXML 根元素的 fx:controller 属性中指定的类的实例。然后,当fx:id 属性与字段名称匹配时,它将 FXML 文件中定义的元素注入到控制器实例它创建的中。然后它在该实例上调用initialize() 方法。

您使用new SearchController()“手动”创建控制器实例。这与FXMLLoader 创建的对象不同。因此,现在当您加载 fxml 文件时,您有两个不同的 SearchController 实例。因此,如果您从display() 方法调用what.setText(...),则不会在FXMLLoader 创建的控制器实例上调用它。因此,what 尚未在您调用 what.setText(...) 的实例中初始化,并且您会收到空指针异常。

由于initialize() 在它创建的实例上由FXMLLoader 调用,当您从initialize() 方法调用what.setText(...) 时,您是在由FXMLLoader 创建的实例上调用它,因此该实例的 FXML 注入字段已初始化。

【讨论】:

  • 感谢您的解释,我刚刚开始使用 JavaFX,所以对我来说还不是很清楚。那么打开新窗口的好方法是什么?不只是在这种情况下,一般?因为直到现在我都认为我应该通过创建控制器类的新对象来做到这一点。
  • 使用默认设置,FXMLLoader 从 fxml 文件创建控制器,因此在该设置中您永远不应该自己创建控制器对象。 display() 方法中的代码正是创建新窗口并在其中显示 fxml 文件内容所需的代码,但在控制器类中将此作为实例方法没有意义;您通常只需要在应用程序中需要创建窗口的位置使用此代码。
  • 哦,我明白了。再次感谢,看来我误解了这个概念。另一个简单的问题:这:SearchController a = loader.getController() 不会创建新实例,对吗?我想我现在明白了,谢谢你:D
  • 是的,这是正确的:loader.getController() 为您提供了加载程序创建的控制器(您需要在调用 load() 后调用它,原因如果您仔细考虑一下就会变得明显)
猜你喜欢
  • 2014-05-18
  • 2016-08-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多