【问题标题】:FXML Variables not bindingFXML 变量不绑定
【发布时间】:2015-01-07 01:48:54
【问题描述】:

我的 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。但是,在测试时,当我尝试将项目加载到我的树视图时,我得到了 NPE。我使用 if 语句确认我的 3 个字段是 null。堆栈跟踪如下:

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

事实证明我的@FXML closeProgram() 和我的@FXML addNewNote() 函数可以正常传递。

谁能指出我错过了什么/做错了什么?

【问题讨论】:

    标签: java javafx javafx-8 fxml


    【解决方案1】:

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

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

    因此,您的构造函数在noteTreeFXMLLoader 初始化之前执行(当然,这是唯一可能发生的事情的顺序)。因此,当您调用

        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();
    
        }
    
        // ...
    }
    

    【讨论】:

    • 那确实不敢相信我一直在努力解决这个问题。谢谢!
    猜你喜欢
    • 2018-12-20
    • 1970-01-01
    • 2014-02-11
    • 2014-02-25
    • 1970-01-01
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    • 2023-03-11
    相关资源
    最近更新 更多