FXML变量没有约束力 [英] FXML Variables not binding

查看:141
本文介绍了FXML变量没有约束力的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am having an issue with my FXML injection. I have setup my program as far as I can tell but it seems that I am missing something. My code is below:

主要:

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。我确认使用if语句,我的3个字段是 null 。堆栈跟踪如下:

Scenebuilder recognizes the fields that I'm injecting noteTree, sp , and newNoteButton. However when testing I am getting a NPE when I try to load items to my treeview. I confirmed using if statements that my 3 fields are null. The stack trace is below:

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

另外,因为它结果是我的 @ FXML closeProgram()和我的 @FXML addNewNote()函数正在传递确定。

Also as it turns out my @FXML closeProgram() and my @FXML addNewNote() functions are being passed ok.

有人能指出我遗失/做错了吗?

Can anyone point out what I am missing/doing wrong?

推荐答案

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

You are trying to set the root item of the tree view in the controller's constructor.

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

When the FXMLLoader loads the fxml file, it will parse the fxml file, noting any fx:id attributes. It will instantiate the controller (by calling it's no-arg constructor), and then it will initialize any @FXML-annotated fields with the corresponding objects with matching fx:id attributes. When that is done, it calls the controller's initialize() method, if there is one.

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

So your constructor is executed before the noteTree is initialized by the FXMLLoader (and of course, this is the only order in which things could possibly happen). Hence when you call

    noteTree.setRoot(rootItem);

noteTree 仍然是 null

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

The fix is simply to move the code in the constructor to the initialize method:

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

    }

    // ...
}

这篇关于FXML变量没有约束力的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆