JavaFX,标签空指针异常

JavaFX, Label null pointer exception

提问人:TimNeutron 提问时间:3/24/2016 更新时间:3/24/2016 访问量:8704

问:

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

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

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();

先谢谢你

JavaFX NullPointerException 标签

评论

0赞 James_D 3/24/2016
顺便说一句,请注意,如果您最终加载了两次FXML文件(并且同时显示两个文件),您的字段将是一场灾难。你根本不需要这些,它们是等待发生的错误。您可以使用关闭窗口(并删除该字段。如果你真的需要这个字段,把它变成一个实例变量,然后从fxml文件中注入它(即删除并放在fxml的根元素上)。staticcancelButton.setOnAction(e -> cancelButton.getScene().getWindow().hide());stageborderPanestaticfx:id="borderPane"

答:

6赞 James_D 3/24/2016 #1

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

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

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

有关此问题的其他信息,请参阅以下答复:

评论

0赞 TimNeutron 3/24/2016
谢谢你的解释,我刚刚开始 JavaFX,所以我还不是很清楚。那么打开新窗口的好方法是什么呢?不仅仅是在这种情况下,一般来说?因为直到现在,我认为我应该通过创建控制器类的新对象来做到这一点。
1赞 James_D 3/24/2016
使用默认设置时,从 fxml 文件创建控制器,因此在该设置中,您永远不应该自己创建控制器对象。方法中的代码正是创建新窗口并在其中显示 fxml 文件内容所需的代码,但是将其作为控制器类中的实例方法没有意义;通常,在应用程序中需要创建窗口的位置上,只需使用此代码即可。FXMLLoaderdisplay()
0赞 TimNeutron 3/24/2016
哦,我明白。再次感谢,看来我误解了这个概念。只是另一个快速问题:这:不会创建一个新实例,对吗?我想我现在明白了这个概念,多亏了你:DSearchController a = loader.getController()
1赞 James_D 3/24/2016
是的,没错:给你加载器创建的控制器(你需要在调用后调用它,如果你稍微考虑一下,原因就会变得很明显)loader.getController()load()