java中的窗格_编辑JavaFx场景中的窗格

本文解释了空指针异常产生的原因,特别是在JavaFX应用程序中,当@FXML注入的字段未正确初始化时。文章提供了如何避免此类异常的具体解决方案,包括正确设置控制器类的方法。

获得空指针异常的原因是 @FXML -injected字段 flowPane 仅在控制器中初始化 . 您在 Main 的不是控制器的实例上调用 updateFlowPanel() ,因此 flowPane 在该实例中为空,因此 flowPane.getChildren() 抛出空指针异常 .

具体来说: Application.launch() 创建 Application 类的实例并在该实例上调用 start() (以及其他内容) .

默认情况下,调用 FXMLLoader.load() 会创建由FXML根元素中的 fx:controller 属性指定的类的实例 . 在该实例中初始化任何 @FXML 注入的字段,在该实例上调用事件处理程序方法,并在该实例上调用 initialize() 方法 .

由于 Application 和控制器类使用相同的类 Main - 这是 always 错误,因此最终会出现两个 Main 实例 . 你从 start() 调用 updateFlowPanel() ,即你在 Application.launch() 创建的实例上调用它;但 flowPane 仅在 FXMLLoader 创建的实例中初始化 .

您应该使用单独的控制器类 . 即做

package renderable;

import javafx.application.Application;

import javafx.fxml.FXMLLoader;

import javafx.scene.Parent;

import javafx.scene.Scene;

import javafx.stage.Stage;

public class Main extends Application {

public static void main(String[] args){

launch(args);

}

@Override

public void start(Stage primaryStage) throws Exception {

Parent root = FXMLLoader.load(getClass().getResource("/renderable/ClientRender.fxml"));

Scene scene = new Scene(root, 1000, 720);

primaryStage.setTitle("The Game");

primaryStage.setScene(scene);

primaryStage.show();

primaryStage.show();

}

}

然后定义一个控制器类:

package renderable ;

import javafx.fxml.FXML ;

import javafx.scene.layout.FlowPane ;

import javafx.scene.control.Button ;

public class Controller {

@FXML

private FlowPane flowPane ;

public void updateFlowPanel(){

Button button = new Button("...");

flowPane.getChildren().add(button);

}

}

并更新FXML以引用它:

nodeOrientation="LEFT_TO_RIGHT" prefHeight="480.0" prefWidth="600.0"

prefWrapLength="1400.0" style="-fx-background-color: #006600;" vgap="4.0"

BorderPane.alignment="CENTER" xmlns="http://javafx.com/javafx/8"

xmlns:fx="http://javafx.com/fxml/1"

fx:controller="renderable.Controller"/>

现在你可以在 initialize() 方法中调用 updateFlowPanel() :

package renderable ;

import javafx.fxml.FXML ;

import javafx.scene.layout.FlowPane ;

import javafx.scene.control.Button ;

public class Controller {

@FXML

private FlowPane flowPane ;

public void initialize() {

updateFlowPanel();

}

public void updateFlowPanel(){

Button button = new Button("...");

flowPane.getChildren().add(button);

}

}

或者您可以使用 start() 方法在正确的控制器实例上调用它:

@Override

public void start(Stage primaryStage) throws Exception {

FXMLLoader loader = new FXMLLoader(getClass().getResource("/renderable/ClientRender.fxml"));

Parent root = loader.load();

Controller controller = loader.getController();

controller.updateFlowPanel();

Scene scene = new Scene(root, 1000, 720);

primaryStage.setTitle("The Game");

primaryStage.setScene(scene);

primaryStage.show();

primaryStage.show();

}

编辑:

您对问题所做的更新实际上会阻止代码编译 . 如果您通过替换修复编译错误

loader.getController().updateFlowPanel();

loader.getController().updateFlowPanel();

那么你创建的(完全不同的)问题就是你创建了一个 FXMLLoader 的实例:

FXMLLoader loader = new FXMLLoader();

但是后来不是使用 FXMLLoader 实例来加载FXML,而是调用静态方法load(URL):

Parent root = loader.load(getClass().getResource("/renderable/ClientRender.fxml"));

由于您正在调用静态方法,因此您永远不会在 FXMLLoader 实例上调用 load() ,因此它的 controller 属性永远不会被初始化 . 因此, loader.getController() 为null, loader.getController().updateFlowPanel() 抛出空指针异常(完全不同于您在先前版本的问题中的空指针异常;它甚至不会从同一方法抛出) .

如果要引用控制器,请使用我在上面发布的 start() 方法的第二个版本中的代码 .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值