如何解决使用带有外部库的自定义组件的 SceneBuilder 打开 FXML 导致 java.lang.ClassNotFoundException
嗨,如果我在 SceneBuilder 中使用在构造函数或初始化方法中使用外部库的自定义组件,当尝试使用 JavaFX SceneBuilder 8.5.0 打开 FXML 时,我会收到 java.lang.classNotFoundException 异常。
我按照此处的说明进行操作:https://docs.oracle.com/javafx/2/fxml_get_started/custom_control.htm。 自定义组件是我的 Eclipse 项目的一部分。我不想将其导出为外部 jar 文件。
当我在 Eclipse 中运行此应用程序时,一切正常。外部库“FontAwesomeIcon”是我在 Eclipse 中构建路径的一部分。
当我尝试使用 SceneBuilder(使用终端获取调试日志)打开自定义组件的 FXML 时,我得到以下输出并且没有加载任何文件:
/Applications/SceneBuilder.app/Contents/MacOS/SceneBuilder /Users/phillip/MEGA/Eclipse/JTunes/src/test/Testwindow.fxml
Jan 09,2021 6:31:44 PM com.oracle.javafx.scenebuilder.app.SceneBuilderApp logTimestamp
informatION: JavaFX Scene Builder started
TestComponent()
TestComponent: Init
Jan 09,2021 6:31:45 PM com.oracle.javafx.scenebuilder.app.SceneBuilderApp$SceneBuilderuncaughtExceptionHandler uncaughtException
SCHWERWIEGEND: An exception was thrown:
java.lang.NoClassDefFoundError: de/jensd/fx/glyphs/fontawesome/FontAwesomeIcon
at test.TestComponent.initialize(TestComponent.java:28)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2548)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at test.TestComponent.<init>(TestComponent.java:22)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.class.newInstance(Class.java:442)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1009)
at javafx.fxml.FXMLLoader$ValueElement.processstartElement(FXMLLoader.java:746)
at javafx.fxml.FXMLLoader.processstartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2425)
at com.oracle.javafx.scenebuilder.kit.fxom.FXOmloader.load(FXOmloader.java:93)
at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.<init>(FXOMDocument.java:89)
at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.<init>(FXOMDocument.java:106)
at com.oracle.javafx.scenebuilder.kit.editor.EditorController.updateFxomDocument(EditorController.java:2540)
at com.oracle.javafx.scenebuilder.kit.editor.EditorController.setFxmlTextAndLocation(EditorController.java:761)
at com.oracle.javafx.scenebuilder.app.DocumentwindowController.loadFromFile(DocumentwindowController.java:385)
at com.oracle.javafx.scenebuilder.app.SceneBuilderApp.performOpenFiles(SceneBuilderApp.java:672)
at com.oracle.javafx.scenebuilder.app.SceneBuilderApp.access$100(SceneBuilderApp.java:98)
at com.oracle.javafx.scenebuilder.app.SceneBuilderApp$1.invalidated(SceneBuilderApp.java:524)
at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:137)
at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
at javafx.beans.property.ReadOnlyBooleanPropertyBase.fireValueChangedEvent(ReadOnlyBooleanPropertyBase.java:72)
at javafx.beans.property.ReadOnlyBooleanWrapper.fireValueChangedEvent(ReadOnlyBooleanWrapper.java:103)
at javafx.beans.property.BooleanPropertyBase.markInvalid(BooleanPropertyBase.java:110)
at javafx.beans.property.BooleanPropertyBase.set(BooleanPropertyBase.java:144)
at com.oracle.javafx.scenebuilder.kit.library.user.UserLibrary.lambda$updateFirstExplorationCompleted$6(UserLibrary.java:352)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.invokelaterdispatcher$Future.run(invokelaterdispatcher.java:95)
Caused by: java.lang.classNotFoundException: de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon
at java.net.urlclassloader.findClass(urlclassloader.java:381)
at java.lang.classLoader.loadClass(ClassLoader.java:424)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
at java.lang.classLoader.loadClass(ClassLoader.java:357)
... 36 more
Jan 09,2021 6:31:46 PM com.oracle.javafx.scenebuilder.app.SceneBuilderApp logTimestamp
informatION: JavaFX Scene Builder stopped
有人可以向我解释整个事情吗?我不明白为什么 SceneBuilder 必须调用构造函数或 initialize 方法。 如果我没有正确理解 JavaFX 和 SceneBuilder 中自定义组件的使用,那么正确的方法是什么?
感谢您的帮助和来自德国的问候。
主类(初始化 JavaFX 应用程序并打开主窗口):
package test;
import javafx.application.Application;
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 {
primaryStage = new Testwindow();
primaryStage.show();
}
}
测试窗口类(加载测试窗口 FXML)。此窗口使用自定义组件:
package test;
import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Testwindow extends Stage {
public Testwindow() throws IOException {
System.out.println("Testwindow()");
FXMLLoader loader = new FXMLLoader();
loader.setController(this);
loader.setLocation(this.getClass().getResource("Testwindow.fxml"));
Parent root = loader.load();
Scene scene = new Scene(root);
this.setScene(scene);
}
}
测试窗口的FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.layout.VBox?>
<?import test.TestComponent?>
<VBox alignment="CENTER" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TestComponent />
</children>
</VBox>
自定义组件类(使用会导致 SceneBuilder 崩溃的外部库“FontAwesomeIcon” - 对应的行是粗体):
package test;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import de.jensd.fx.glyphs.fontawesome.FontAwesomeIcon;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.layout.VBox;
public class TestComponent extends VBox implements Initializable {
public TestComponent() throws IOException {
System.out.println("TestComponent()");
FXMLLoader loader = new FXMLLoader();
loader.setController(this);
loader.setRoot(this);
loader.setLocation(this.getClass().getResource("TestComponent.fxml"));
loader.load();
}
@Override
public void initialize(URL location,ResourceBundle resources) {
System.out.println("TestComponent: Init");
System.out.println("TestComponent: "+FontAwesomeIcon.ADJUST);
}
@FXML
private void click() {
System.out.println("Click");
}
}
自定义组件的 FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.VBox?>
<fx:root alignment="CENTER" type="VBox" xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1">
<children>
<Label text="TestComponent" />
<Button onMouseClicked="#click" text="Button" />
</children>
</fx:root>
更新:
当我将类“de/jensd/fx/glyphs/fontawesome/FontAwesomeIcon”的 .jar 文件添加到 SceneBuilder 配置文件中的“app.classpath”选项时,fxml 毫无例外地打开。
我真的需要将每个外部库都添加到这个设置中吗?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。