当前位置: 首页 > 面试题库 >

FXML变量未绑定

姬俊驰
2023-03-14
问题内容

我的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()功能都可以通过。

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


问题答案:

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

FXMLLoader负载FXML文件,它将解析FXML文件,并指出任何fx:id属性。它将实例化控制器(通过调用其no-
arg构造函数),然后它将@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();

    }

    // ...
}


 类似资料:
  • 从正在运行的javafx应用程序打开新的javafx窗口时,我无法将fxml变量绑定到控制器类中的局部变量。 请注意,对于正在运行的应用程序,我可以毫无问题地绑定到同名变量,在运行时在正在运行的应用程序中填充ComboBox。欢迎任何解决方案。 调用新类的代码(ServerConfigChooser) 在运行的应用程序中工作的绑定示例(运行时执行的代码) 控制器类中的fxid“cb_01_fxid

  • 变量绑定默认是不可变的,但加上 mut 修饰语后变量就可以改变。 fn main() { let _immutable_binding = 1; let mut mutable_binding = 1; println!("Before mutation: {}", mutable_binding); // 正确代码 mutable_binding += 1

  • Rust 通过静态类型确保类型安全。变量绑定可以在声明变量时标注类型。不过在多数情况下,编译器能够 从字面内容推导出变量的类型,大大减少了标注类型的负担。 使用 let 绑定操作可以将值(像具体数据)绑定到变量中。 fn main() { let an_integer = 1u32; let a_boolean = true; let unit = (); // 将

  • Rust 语言可以先声明变量绑定,后面才将它们初始化。但是这种情况用得很少,因为这样很可能导致使用未 初始的变量。 fn main() { // 声明一个变量绑定 let a_binding; { let x = 2; // 初始化一个绑定 a_binding = x * x; } println!("a bi

  • 事实上每一个非“Hello World” Rust 程序都用了变量绑定。他们将一些值绑定到一个名字上,这样可以在之后使用他们。let被用来声明一个绑定,像这样: fn main() { let x = 5; } 在每个例子中都写上fn main() {有点冗长,所以之后我们将省略它。如果你是一路看过来的,确保你写了main()函数,而不是省略不写。否则,你将得到一个错误。 模式(Patt

  • 我目前正在为我的学习做一个Java(+使用MySQL)应用程序:一个Hopital的数据库 我使用JavaFX编写接口代码。我有一个主FXML(用于一般视图),其中有选项卡,在每个选项卡中,我使用(fx:include)导入另一个FXML。以便我的应用程序的每个模块都有自己的控制器和自己设计的视图。 如何将变量从主控制器传递给其他控制器? 谢谢!编辑:让我给你看我的代码 首先,这是我加载我的fxm