FXML变量没有约束力

时间:2015-01-07 01:48:55

标签: java javafx javafx-8 fxml

我的FXML注射有问题。据我所知,我已经设置了我的程序,但似乎我错过了一些东西。我的代码如下:

主:

package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;


public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {

        try {

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

            BorderPane root = (BorderPane)loader.load();
            Scene scene = new Scene(root,root.getHeight(),root.getWidth());
            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);
    }
}

控制器:

package application;




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

import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.ScrollPane;
import javafx.scene.control.TreeItem;
import javafx.scene.control.TreeView;
import javafx.scene.layout.BorderPane;

public class NoteKeeperController implements Initializable{
    NoteBook noteBook;
    TreeItem<String> rootItem;

    public BorderPane root;

    @FXML private TreeView<String> noteTree;

    @FXML private ScrollPane sp;
    @FXML private Button newNoteButton;
    public NoteKeeperController(){

        rootItem = new TreeItem<String> ("FirstNote");
        rootItem.setExpanded(true);     
        noteTree.setRoot(rootItem);

        noteBook= new NoteBook();

    }
    @FXML
    private void closeProgram(){
        System.exit(0);
    }

    @FXML
    private void addNewNote(){
        Note note = noteBook.newNote("test", "Problem");
        TreeItem<String> newItem= new TreeItem<>(note.getNoteName());
        rootItem.getChildren().add(newItem);
    }

    public BorderPane getRoot() {
        return root;
    }

    public void setRoot(BorderPane root) {
        this.root = root;
    }

@Override
public void initialize(URL location, ResourceBundle resources) {
    // TODO Auto-generated method stub

}

}

FXML文件:

<BorderPane fx:id="root" prefHeight="719.0" prefWidth="893.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8" fx:controller="application.NoteKeeperController">
   <center>
      <BorderPane prefHeight="641.0" prefWidth="872.0" BorderPane.alignment="CENTER">
         <center>
            <TabPane prefHeight="200.0" prefWidth="200.0" tabClosingPolicy="UNAVAILABLE" BorderPane.alignment="CENTER">
              <tabs>
                <Tab text="Untitled Tab 1">
                  <content>
                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
                  </content>
                </Tab>
                <Tab text="Untitled Tab 2">
                  <content>
                    <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
                  </content>
                </Tab>
              </tabs>
            </TabPane>
         </center>
         <left>
            <ScrollPane fx:id="sp" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
              <content>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="650.0" prefWidth="200.0">
                     <children>
                        <TreeView fx:id="noteTree" prefHeight="650.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0" />
                     </children>

Scenebuilder识别我正在注入 noteTree,sp和newNoteButton 的字段。但是在测试时,当我尝试将项目加载到我的树视图时,我得到了一个N​​PE。我确认使用我的3个字段为null的if语句。堆栈跟踪如下:

Caused by: java.lang.NullPointerException
    at application.NoteKeeperController.<init>(NoteKeeperController.java:31)

另外,事实证明我的@FXML closeProgram()和我的@FXML addNewNote()功能正在通过。

有人能说出我错过了什么/做错了吗?

1 个答案:

答案 0 :(得分:4)

您正在尝试在控制器的构造函数中设置树视图的根项。

FXMLLoader加载fxml文件时,它将解析fxml文件,并注明任何fx:id属性。它将实例化控制器(通过调用它的无参数构造函数),然后它将使用具有匹配@FXML属性的相应对象初始化任何fx:id - 带注释的字段。完成后,它会调用控制器的initialize()方法(如果有)。

所以你的构造函数是在noteTree初始化FXMLLoader之前执行的(当然,这是事情可能发生的唯一顺序)。因此,当你打电话

    noteTree.setRoot(rootItem);

noteTree仍为null

修复只是将构造函数中的代码移动到initialize方法:

public class NoteKeeperController implements Initializable{
    NoteBook noteBook;
    TreeItem<String> rootItem;

    public BorderPane root;

    @FXML private TreeView<String> noteTree;

    @FXML private ScrollPane sp;
    @FXML private Button newNoteButton;

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

        rootItem = new TreeItem<String> ("FirstNote");
        rootItem.setExpanded(true);     
        noteTree.setRoot(rootItem);

        noteBook= new NoteBook();

    }

    // ...
}