微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

使用带有外部库的自定义组件的 SceneBuilder 打开 FXML 导致 java.lang.ClassNotFoundException

如何解决使用带有外部库的自定义组件的 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 举报,一经查实,本站将立刻删除。