我是JavaFX, FXML和SceneBuilder的新手。我正在为一个项目工作,我必须建立一个应用程序,其中包括显示不同的讲座资料的功能。不同的配置文件存储在数据库中,并且都是一个名为"lecture"的类的实例。我用SceneBuilder为这个类构建了第一个简单的场景,并创建了一个控制器类。现在的想法是,每当一个讲座应该显示根据对象从数据库中加载,并用于调整控制器类的属性,导致场景的变化。我通过在start()方法中实例化Lecture对象并将其传递给类似getter的方法来模拟这一点,该方法应该更改显示讲师名称的第一个标签属性的文本。不幸的是,这会导致NullPointerException。所有的研究都帮不上忙所以我才来找你。我很感激任何帮助!
GUI图片:
GUI
错误信息与stacktrace:
> Task :Main.main() FAILED
Juni 23, 2022 12:16:04 AM com.sun.javafx.application.PlatformImpl startup
WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @1796cf6c'
Unsupported JavaFX configuration: classes were loaded from 'unnamed module @1796cf6c'
Juni 23, 2022 12:16:04 AM javafx.fxml.FXMLLoader$ValueElement processValue
WARNING: Loading FXML document with JavaFX API of version 18 by JavaFX runtime of version 17.0.1
Exception in Application start method
Loading FXML document with JavaFX API of version 18 by JavaFX runtime of version 17.0.1
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:901)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:196)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.NullPointerException: Cannot invoke "unihub.userapplicationsystem.LectureProfileController.loadLecture(unihub.serversystem.model.Lecture)" because "lectureProfileController" is null
at unihub.userapplicationsystem.GUI.start(GUI.java:25)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:847)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:484)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
Caused by: java.lang.NullPointerException: Cannot invoke "unihub.userapplicationsystem.LectureProfileController.loadLecture(unihub.serversystem.model.Lecture)" because "lectureProfileController" is null
at com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Execution failed for task ':Main.main()'.
> Process 'command '/Library/Java/JavaVirtualMachines/jdk-17.0.1.jdk/Contents/Home/bin/java'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
JavaFX应用程序类:
package unihub.userapplicationsystem;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import unihub.serversystem.model.Lecture;
import java.net.URL;
public class GUI extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
URL lectureProfileStageUML = ClassLoader.getSystemResource("LectureProfileStage.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
Parent root = fxmlLoader.load(lectureProfileStageUML);
Lecture testLecture = new Lecture(1, "EIST", "Krusche");
LectureProfileController lectureProfileController = fxmlLoader.getController();
lectureProfileController.loadLecture(testLecture);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
主类:
public class Main {
public static void main(String[] args) {
GUI.main(args);
}
}
FXML控制器类:
package unihub.userapplicationsystem;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import unihub.serversystem.model.Lecture;
public class LectureProfileController {
private Lecture lecture;
@FXML
private Label lecturerNameLabel;
public void loadLecture(Lecture lecture) {
lecturerNameLabel.setText("lecturer:n" + lecture.getLecturer());
}
}
FXML文件:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.FlowPane?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.layout.StackPane?>
<?import javafx.scene.text.Font?>
<ScrollPane prefHeight="500.0" prefWidth="400.0" xmlns="http://javafx.com/javafx/18" xmlns:fx="http://javafx.com/fxml/1" fx:controller="unihub.userapplicationsystem.LectureProfileController">
<content>
<FlowPane prefHeight="500.0" prefWidth="400.0">
<children>
<StackPane prefHeight="100.0" prefWidth="400.0">
<children>
<ImageView fitHeight="100.0" fitWidth="400.0" pickOnBounds="true" preserveRatio="false">
<image>
<Image url="@LectureBanner.jpg" />
</image>
</ImageView>
<Label text="lecture name here" translateX="-85.0" translateY="-20.0" StackPane.alignment="BOTTOM_CENTER">
<font>
<Font name="SansSerif Bold" size="21.0" />
</font>
</Label>
</children>
</StackPane>
<GridPane alignment="BOTTOM_RIGHT" hgap="10.0" nodeOrientation="LEFT_TO_RIGHT" prefHeight="150.0" prefWidth="400.0" vgap="10.0">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="188.0" minWidth="10.0" prefWidth="167.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="173.0" minWidth="10.0" prefWidth="173.0" />
</columnConstraints>
<rowConstraints>
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
</rowConstraints>
<children>
<Label text="lecturer: -lecturer here- " GridPane.halignment="LEFT" fx:id="lecturerNameLabel"/>
<Label text="lecture-ID: -lecture-ID here-" GridPane.halignment="LEFT" GridPane.rowIndex="1" />
<Label text="teaching language: -language here-" GridPane.halignment="LEFT" GridPane.rowIndex="2" />
<Label text="weekly hours: -hours here-" GridPane.columnIndex="1" GridPane.halignment="LEFT" GridPane.rowIndex="1" />
<Label text="number of credits: -credits here-" GridPane.columnIndex="1" GridPane.halignment="LEFT" />
<Button alignment="CENTER" mnemonicParsing="false" prefHeight="10.0" prefWidth="101.0" text="Enroll" GridPane.columnIndex="1" GridPane.rowIndex="2">
<font>
<Font name="SansSerif Regular" size="11.0" />
</font>
</Button>
</children>
<padding>
<Insets left="25.0" right="25.0" top="20.0" />
</padding>
</GridPane>
</children>
</FlowPane>
</content>
</ScrollPane>
FXMLLoader.load(URL)
方法是静态方法。所以你的代码编译成
URL lectureProfileStageUML = ClassLoader.getSystemResource("LectureProfileStage.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
Parent root = FXMLLoader.load(lectureProfileStageUML);
从代码的等效版本中可以明显看出,您定义的实例fxmlLoader
没有被用来加载FXML文件。因此它永远不会初始化它的控制器,并且
LectureProfileController lectureProfileController = fxmlLoader.getController();
返回null,当您尝试执行
时将导致空指针异常。lectureProfileController.loadLecture(testLecture);
相反,您应该设置fxmlLoader
的位置并调用无参数的实例方法fxmlLoader.load()
:
@Override
public void start(Stage primaryStage) throws Exception {
URL lectureProfileStageUML = ClassLoader.getSystemResource("LectureProfileStage.fxml");
FXMLLoader fxmlLoader = new FXMLLoader();
fxmlLoader.setLocation(lectureProfileStageUML);
// or just:
// FXMLLoader fxmlLoader = new FXMLLoader(lectureProfileStageUML);
// Note no URL is passed here:
Parent root = fxmlLoader.load();
Lecture testLecture = new Lecture(1, "EIST", "Krusche");
LectureProfileController lectureProfileController = fxmlLoader.getController();
lectureProfileController.loadLecture(testLecture);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
顺便说一句,URL的结构可能是错误的。请参阅如何确定我的JavaFX应用程序所需的FXML文件、CSS文件、图像和其他资源的正确路径?另外,从实例变量调用静态方法是没有意义的。当您不小心这样做时,大多数ide都会警告您(或者至少可以配置为警告您)。我建议将您的IDE配置为提供警告(而不是忽略警告)。允许这种语法作为有效语法是一个糟糕的设计决策(语言设计者是在复制c++中发生的事情)。