我正在使用Java 20、JavaFX 20和Maven创建一个小型个人项目。我在创建可重用组件并通过主场景控制器操纵它们方面遇到了问题。
首先,我按照官方文档中列出的步骤进行操作。之后,我进入SceneBuilder,在SceneBuilder中导入我的自定义组件的FXML文件(单击“库”处的小引擎图标 -> JAR/FXML管理器 -> 从文件系统添加库/FXML),并像使用任何默认组件一样将其添加到场景中。然后,我为我的自定义组件添加了fx:id,并将其添加到我的场景控制器类中,以便我可以对其进行操作,但是我收到了以下错误信息。
Exception in Application start method
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 javafx.graphics@20/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
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@20/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:893)
at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:1623)
Caused by: javafx.fxml.LoadException:
/C:/Users/user/Desktop/eclipse-workspace/Project 3/target/classes/app/views/fxml/Menu.fxml:43
at javafx.fxml@20/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2722)
at javafx.fxml@20/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2700)
at javafx.fxml@20/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2563)
at javafx.fxml@20/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2531)
at app/app.Main.loadFXML(Main.java:29)
at app/app.Main.start(Main.java:17)
at javafx.graphics@20/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:839)
at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:483)
at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:456)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:400)
at javafx.graphics@20/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:455)
at javafx.graphics@20/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at javafx.graphics@20/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics@20/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:185)
... 1 more
Caused by: java.lang.IllegalArgumentException: Can not set app.components.Custom field app.controllers.Menu.cc to javafx.scene.layout.VBox
at java.base/jdk.internal.reflect.FieldAccessorImpl.throwSetIllegalArgumentException(FieldAccessorImpl.java:228)
at java.base/jdk.internal.reflect.FieldAccessorImpl.throwSetIllegalArgumentException(FieldAccessorImpl.java:232)
at java.base/jdk.internal.reflect.MethodHandleObjectFieldAccessorImpl.set(MethodHandleObjectFieldAccessorImpl.java:115)
at java.base/java.lang.reflect.Field.set(Field.java:834)
at javafx.fxml@20/javafx.fxml.FXMLLoader.injectFields(FXMLLoader.java:1175)
at javafx.fxml@20/javafx.fxml.FXMLLoader$ValueElement.processValue(FXMLLoader.java:870)
at javafx.fxml@20/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:764)
at javafx.fxml@20/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2853)
at javafx.fxml@20/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2649)
... 13 more
Exception running application app.Main
我注意到一个奇怪的事情,就是当我将组件添加到主场景中时,它显示为VBox而不是Custom,尽管在“层次结构”选项卡中拖动组件时,显示组件的名称为Custom,而不是VBox。
以下是相关文件 Custom.java
package app.components;
import java.io.IOException;
import app.Main;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
public class Custom extends VBox {
@FXML private Button plusBtn;
@FXML private Button minusBtn;
@FXML private Label label;
public Custom() {
FXMLLoader loader = new FXMLLoader(Main.class.getResource("components/Custom.fxml"));
loader.setRoot(this);
loader.setController(this);
try {
loader.load();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void newText(String text) {
label.setText(text);
}
}
Custom.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Button fx:id="plusBtn" mnemonicParsing="false" text="+" />
<Label fx:id="label" text="Label" />
<Button fx:id="minusBtn" mnemonicParsing="false" text="-" />
</children>
</VBox>
目前,我的主要场景只是一个空的StackPane,其中心是我自定义的组件,我将其命名为fx:id为"cc"。
Menu.java
package app.controllers;
import app.components.Custom;
public class Menu {
@FXML
private Custom cc;
public void initialize() {
cc.newText("Test");
}
}
module-info.java
module app {
requires javafx.controls;
requires javafx.fxml;
requires javafx.media;
requires javafx.graphics;
requires javafx.base;
opens app to javafx.fxml;
opens app.controllers to javafx.fxml;
exports app;
}
问题在于,当我将组件从“自定义”部分拖放到“StackPane”中时,它显示为“VBox”,而不是“Custom”。这里有一张截图,可能会更清楚地说明我的意思:
我希望组件显示为Custom而不是VBox,因为SceneBuilder告诉我它找不到“cc”的可注入字段,尽管我在控制器类中有该字段。
<fx:root …>
)。 - James_D