JavaFX GUI程序启动报NullPointerException,求解决方案
JavaFX启动时GridPane.add抛出NullPointerException的解决办法
问题概述
运行JavaFX学生注册程序时,启动阶段抛出NullPointerException,错误指向GridPane.add方法调用。
异常栈信息
Exception in Application start method Exception in thread "main" java.lang.reflect.InvocationTargetException at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119) at java.base/java.lang.reflect.Method.invoke(Method.java:578) at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1081) Caused by: java.lang.RuntimeException: Exception in Application start method at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901) at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196) at java.base/java.lang.Thread.run(Thread.java:1589) Caused by: java.lang.NullPointerException: Cannot invoke "javafx.scene.Node.getProperties()" because "<parameter1>" is null at javafx.graphics/javafx.scene.layout.Pane.setConstraint(Pane.java:111) at javafx.graphics/javafx.scene.layout.GridPane.setRowIndex(GridPane.java:299) at javafx.graphics/javafx.scene.layout.GridPane.setConstraints(GridPane.java:556) at javafx.graphics/javafx.scene.layout.GridPane.add(GridPane.java:973) at gslcpertemuanke9/application.Main.PositionSetting(Main.java:135) at gslcpertemuanke9/application.Main.start(Main.java:167) at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456) at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96) at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method) at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184) ... 1 more
问题根源分析
- setValueFactory方法错误返回null:自定义的两个
setValueFactory方法直接返回null,导致AgeSpinner和ClassSpinner被赋值为null,调用GridPane.add时传入null节点触发NPE。 - start方法执行顺序错误:先调用
stage.show()再初始化组件,此时RegisterScene还未被正确初始化,会导致界面显示异常。 - GridPane未添加到BorderPane:初始化的
RegisterGP没有被添加到RegisterBP中,即使修复NPE后也无法看到注册表单。
修复方案
- 修正setValueFactory方法:创建Spinner实例,设置对应的ValueFactory后返回该实例。
- 调整start方法执行顺序:先完成所有组件初始化,再设置场景并显示窗口。
- 将GridPane添加到BorderPane:把
RegisterGP添加到RegisterBP的底部或其他合适位置,保证表单可见。
修复后的完整代码
package application; import javafx.application.Application; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.stage.FileChooser; import javafx.stage.Stage; import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.ScrollPane; import javafx.scene.control.Spinner; import javafx.scene.control.SpinnerValueFactory; import javafx.scene.control.SpinnerValueFactory.DoubleSpinnerValueFactory; import javafx.scene.control.SpinnerValueFactory.IntegerSpinnerValueFactory; import javafx.scene.control.TableColumn; import javafx.scene.control.TableView; import javafx.scene.control.TextArea; import javafx.scene.control.TextField; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.BorderPane; import javafx.scene.layout.GridPane; public class Main extends Application { Stage stage; Scene RegisterScene; BorderPane RegisterBP; GridPane RegisterGP; Label RegistLbl; Label NameLabel, AgeLabel, ClassLabel, SchoolLabel; TextField NameField; TextArea AddressTA; Spinner<Integer> AgeSpinner; Spinner<Double> ClassSpinner; ComboBox<String> SchoolBox; Button SubmitButton, DeleteButton, OpenFileButton; FileChooser FileChooser; TableView<Student> table; TableColumn<Student, String> NameColumn, SchoolColumn; TableColumn<Student, Integer> AgeColumn; TableColumn<Student, Double> ClassColumn; Alert NameAlert; ScrollPane sp; public void initialize() { RegisterBP = new BorderPane(); RegisterScene = new Scene(RegisterBP, 1366, 768); RegisterGP = new GridPane(); sp = new ScrollPane(); sp.setContent(RegisterBP); sp.setFitToWidth(true); RegistLbl = new Label("Registration"); NameLabel = new Label("Name"); AgeLabel = new Label("Age"); ClassLabel = new Label("Class"); SchoolLabel = new Label("School origin"); NameField = new TextField(); AgeSpinner = setValueFactory(new IntegerSpinnerValueFactory(1, 100, 1)); ClassSpinner = setValueFactory(new DoubleSpinnerValueFactory(1, 100, 1)); AddressTA = new TextArea(); SchoolBox = new ComboBox<>(); SchoolBox.getItems().addAll("Otonokizaka High School", "Uranohoshi Girls High School", "Nijigasaki High School"); SchoolBox.getSelectionModel().selectFirst(); SubmitButton = new Button("Register"); DeleteButton = new Button("Delete"); OpenFileButton = new Button("Open File"); FileChooser = new FileChooser(); } private Spinner<Double> setValueFactory(DoubleSpinnerValueFactory doubleSpinnerValueFactory) { Spinner<Double> spinner = new Spinner<>(); spinner.setValueFactory(doubleSpinnerValueFactory); return spinner; } private Spinner<Integer> setValueFactory(IntegerSpinnerValueFactory integerSpinnerValueFactory) { Spinner<Integer> spinner = new Spinner<>(); spinner.setValueFactory(integerSpinnerValueFactory); return spinner; } public void TableInitialization() { table = new TableView<>(); NameColumn = new TableColumn<Student, String>("Name"); NameColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("name")); NameColumn.setMinWidth(RegisterBP.getWidth() / 4); AgeColumn = new TableColumn<Student, Integer>("Age"); AgeColumn.setCellValueFactory(new PropertyValueFactory<Student, Integer>("age")); AgeColumn.setMinWidth(RegisterBP.getWidth() / 4); ClassColumn = new TableColumn<Student, Double>("Class"); ClassColumn.setCellValueFactory(new PropertyValueFactory<Student, Double>("class")); ClassColumn.setMinWidth(RegisterBP.getWidth() / 4); SchoolColumn = new TableColumn<Student, String>("School origin"); SchoolColumn.setCellValueFactory(new PropertyValueFactory<Student, String>("school")); SchoolColumn.setMinWidth(RegisterBP.getWidth() / 4); table.getColumns().addAll(NameColumn, AgeColumn, ClassColumn, SchoolColumn); } public void initAlert() { NameAlert = new Alert(AlertType.ERROR); NameAlert.setHeaderText("Invalid name!"); NameAlert.setContentText("You must insert at least 3 characters"); } public void PositionSetting() { RegisterGP.add(NameLabel, 0, 0); RegisterGP.add(AgeLabel, 0, 1); RegisterGP.add(ClassLabel, 0, 2); RegisterGP.add(SchoolLabel, 0, 3); RegisterGP.add(SubmitButton, 0, 4); RegisterGP.add(NameField, 1, 0); RegisterGP.add(AgeSpinner, 1, 1); RegisterGP.add(ClassSpinner, 1, 2); RegisterGP.add(SchoolBox, 1, 3); RegisterGP.add(DeleteButton, 1, 4); RegisterGP.setHgap(15); RegisterGP.setVgap(10); RegisterGP.setPadding(new Insets(10)); RegisterBP.setTop(RegistLbl); RegisterBP.setCenter(table); RegisterBP.setBottom(RegisterGP); } public void SetEventHandler() { SubmitButton.setOnAction((EventHandler<ActionEvent>) this); DeleteButton.setOnAction((EventHandler<ActionEvent>) this); OpenFileButton.setOnAction((EventHandler<ActionEvent>) this); } @Override public void start(Stage primaryStage) throws Exception { stage = primaryStage; initialize(); TableInitialization(); PositionSetting(); SetEventHandler(); initAlert(); stage.setScene(RegisterScene); stage.setTitle("Student List"); stage.show(); } }
注:需要确保
Student实体类已正确实现,包含name、age、class、school属性的getter方法,否则TableView无法正常显示数据。
内容的提问来源于stack exchange,提问作者Johnny
相关产品推荐
相关产品推荐

