获得空指针异常的原因是 @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() 方法的第二个版本中的代码 .
本文解释了空指针异常产生的原因,特别是在JavaFX应用程序中,当@FXML注入的字段未正确初始化时。文章提供了如何避免此类异常的具体解决方案,包括正确设置控制器类的方法。
1150

被折叠的 条评论
为什么被折叠?



