具有外部依赖性的JavaFX Gluon Scene Builder自定义组件

时间:2017-07-01 15:45:19

标签: java scenebuilder gluon

我有两个项目:Components和MyApp。

组件项目有两个文件:

mycomponents/MyComponent.fxml
mycomponents/MyComponent.java

MyComponent.fxml使用ikonli,项目中包含ikonli-core-1.9.0.jarikonli-javafx-1.9.0.jarikonli-material-pack-1.9.0.jar(我认为编译项目ikonli-javafx-1.9.0.jar已经足够了)

MyComponent.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import org.kordamp.ikonli.javafx.FontIcon?>


<fx:root type="javafx.scene.layout.AnchorPane" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111">
   <children>
      <Button mnemonicParsing="false">
         <graphic>
            <FontIcon iconLiteral="gmi-check-circle" iconSize="24" />
         </graphic>
      </Button>
   </children>
</fx:root>

MyComponent.java:

package mycomponents;

import java.io.IOException;
import javafx.fxml.FXMLLoader;
import javafx.scene.layout.AnchorPane;

public class MyComponent extends AnchorPane {
    public MyComponent() {
        FXMLLoader loader = new FXMLLoader(MyComponent.class.getResource("MyComponent.fxml"));
        loader.setRoot(this);
        loader.setController(this);
        try {
            loader.load();
        } catch (IOException exception) {
            throw new RuntimeException(exception);
        }
    }
}

项目编译成功,我可以在Scene Builder中打开MyComponent.fxml(因为我将三个ikonli罐导入Scene Builder(通过存储库搜索))。 编译组件项目后,我将Components.jar导入到Scene Builder中,Library Manger中的情况为:

Library Manager screenshot

MyApp项目有三个文件:

myapp/FXMLDocument.fxml
myapp/FXMLDocumentController.java
myapp/MyApp.java

FXMLDocument.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import mycomponents.MyComponent?>

<AnchorPane xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="myapp.FXMLDocumentController">
    <children>
        <MyComponent />
    </children>
</AnchorPane>

FXMLDocumentController.java:

package myapp;

import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.Initializable;

public class FXMLDocumentController implements Initializable {
    @Override
    public void initialize(URL url, ResourceBundle rb) {
        // TODO
    }    
}

MyApp.java:

package myapp;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class MyApp extends Application {
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        Scene scene = new Scene(root);
        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }    
}

我添加了三个ikonli个罐子和Components.jar。项目编译得很好,我可以运行应用程序,一切正常。

但是当我想用Scene Builder打开FXMLDocument.fxml时,我收到了这个错误:

java.io.IOException: javafx.fxml.LoadException: 
/C:/Users/user/Documents/NetBeansProjects/MyApp/src/myapp/FXMLDocument.fxml:9

    at com.oracle.javafx.scenebuilder.kit.fxom.FXOMLoader.load(FXOMLoader.java:92)
    at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.<init>(FXOMDocument.java:82)
    at com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument.<init>(FXOMDocument.java:97)
    at com.oracle.javafx.scenebuilder.kit.editor.EditorController.updateFxomDocument(EditorController.java:2384)
    at com.oracle.javafx.scenebuilder.kit.editor.EditorController.setFxmlTextAndLocation(EditorController.java:664)
    at com.oracle.javafx.scenebuilder.app.DocumentWindowController.loadFromFile(DocumentWindowController.java:385)
    at com.oracle.javafx.scenebuilder.app.SceneBuilderApp.performOpenFiles(SceneBuilderApp.java:634)
    at com.oracle.javafx.scenebuilder.app.SceneBuilderApp.access$200(SceneBuilderApp.java:84)
    at com.oracle.javafx.scenebuilder.app.SceneBuilderApp$1.invalidated(SceneBuilderApp.java:496)
    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$7(UserLibrary.java:324)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)
Caused by: javafx.fxml.LoadException: 
/C:/Users/user/Documents/NetBeansProjects/MyApp/src/myapp/FXMLDocument.fxml:9

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2425)
    at com.oracle.javafx.scenebuilder.kit.fxom.FXOMLoader.load(FXOMLoader.java:89)
    ... 22 more
Caused by: java.lang.RuntimeException: javafx.fxml.LoadException: 
file:/C:/Users/user/AppData/Roaming/Scene%20Builder/Library/Components.jar!/mycomponents/MyComponent.fxml

    at mycomponents.MyComponent.<init>(MyComponent.java:15)
    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)
    ... 24 more
Caused by: javafx.fxml.LoadException: 
file:/C:/Users/user/AppData/Roaming/Scene%20Builder/Library/Components.jar!/mycomponents/MyComponent.fxml

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
    at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2848)
    at javafx.fxml.FXMLLoader.processImport(FXMLLoader.java:2692)
    at javafx.fxml.FXMLLoader.processProcessingInstruction(FXMLLoader.java:2661)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2517)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
    at mycomponents.MyComponent.<init>(MyComponent.java:13)
    ... 34 more
Caused by: java.lang.ClassNotFoundException: org.kordamp.ikonli.javafx.FontIcon
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at javafx.fxml.FXMLLoader.loadTypeForPackage(FXMLLoader.java:2916)
    at javafx.fxml.FXMLLoader.loadType(FXMLLoader.java:2905)
    at javafx.fxml.FXMLLoader.importClass(FXMLLoader.java:2846)
    ... 40 more

1 个答案:

答案 0 :(得分:0)

我正面对同样的问题,作为解决方法,我提取de.jar依赖项,然后包括我的Component.jar。

我使用gradle构建,这是build.gradle的snipet,其中发生了事情。

&#39; XXX&#39;是我的图书馆名称;

...
dependencies {
...
   compile 'br.com.emorgado:XXX:1.0.0-SNAPSHOT'
...
}

task extractTransitiveDependencies(type: Copy) {
    into "$buildDir/classes/main"
    from {
        configurations.compile.filter{
            it.name.startsWith('XXX')
        }
        .collect {
            zipTree( it )
        }
    }
}

jar.dependsOn extractTransitiveDependencies

jar {
    doFirst {    
    copy{
       from("$buildDir/output/lib/br/com/emorgado/"){
        exclude 'META-INF'
       }
       into("/br/com/emorgado/") // <- this is my component folder
}
...