繁体   English   中英

Scene Builder嵌套的自定义节点

[英]Scene Builder Nested Custom Nodes

我似乎在Scene Builder 8.4.1中遇到了一个非常严重的错误,其他人之前在不同版本中都曾遇到过该错误(请参阅链接)。 错误是,当我尝试导入自定义节点时,该自定义节点又从jar文件包含其他自定义节点,仅找到嵌套节点。 即,找不到外部节点。

所以我想知道。 有谁知道一个稳定的Scene Builder版本,该版本对于Java的较新版本(8、9或10,如果尚未发布)没有此错误(最好没有其他严重错误)? 我还希望有一个安装向导,它将为我提供一个exe应用程序而不是一个可运行的jar,以便与我的IDE更好地集成。 如果不存在,那么您还有更多需要Scene Builder经验的人推荐我做什么? 我是否应该使所有fxml文档都没有嵌套节点,并在以后手动添加它们?

谢谢你的帮助!

编辑:所有源文件都可以在这里找到。 请注意,外部容器是SliderVariable,内部容器是InfoIcon。

您可以将两个或多个自定义控件嵌套在同一个jar中,并且可以从您的IDE或命令行中正常运行。

但是,如果从Scene Builder导入该jar,则某些自定义控件如果依赖于其他控件,则可能无法导入。

这是有原因的,最好的是,也有一个简单的解决方案。

如何导入自定义控件?

如果您查看Scene Builder的源代码 ,以导入jar的可能的自定义控件,则有一个JarExplorer类,该类具有explore 方法

该方法基本上会遍历jar中的每个类,以找出该类是否是应添加到用户库中的可能的自定义组件。

最后,如何工作是通过尝试基于该类创建FXML对象:

 entryClass = classLoader.loadClass(className);
 instantiateWithFXMLLoader(entryClass, classLoader);

如果成功,则将该类添加到components集合中。

为什么嵌套的自定义控件无法导入?

那么,为什么不能导入嵌套自定义控件(该嵌套自定义控件具有另一个自定义控件作为依赖项)呢? 可以找到原因来调试Scene Builder,并打印出得到的异常:

try {
    instantiateWithFXMLLoader(entryClass, classLoader);
} catch (RuntimeException | IOException x) {
    status = JarReportEntry.Status.CANNOT_INSTANTIATE;
    x.printStackTrace(); // <-- print exception
} catch (Error | ClassNotFoundException x) {
    status = JarReportEntry.Status.CANNOT_LOAD;
    x.printStackTrace(); // <-- print exception
}

创建任何类型的自定义控件时,记录此内容确实很有帮助。

对于嵌套的自定义控件,如果该依赖关系在类路径中已经可用,并且按类路径,我的意思是Scene Builder预先加载的所有依赖项都不会出现问题。 但是,如果不可用,则FXMLLoader将无法创建该控件的有效实例。

让我们尝试一下SliderVariable控件。 如果您打印出异常,您将看到类似以下内容:

javafx.fxml.LoadException: 
    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.library.util.JarExplorer.instantiateWithFXMLLoader(JarExplorer.java:110)
... 9 more

Caused by: java.lang.RuntimeException: javafx.fxml.LoadException: 
    file:.../SliderVariable-1.0-SNAPSHOT-shaded!/com/coolcompany/slidervariable/SliderVariable.fxml
...
Caused by: java.lang.ClassNotFoundException: com.coolcompany.infoicon.InfoIcon
    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)
... 26 more

因此,从根本上讲,这解释了为什么不导入嵌套控件的原因:内部控件事先在类路径中不可用。

可能的解决方案

显然,您可以将两个控件分别捆绑在一起,先导入InfoIcon控件,然后再导入SliderVariable控件。 但是,如果要在单个依赖项中分发这些控件,则可能会出现问题。

最佳解决方案

因此,如果两个内部控件都在同一个jar中,那么如何在运行时将内部控件提供给外部控件?

这是通过将此外部控件类的类加载器传递给FXMLLoaderFXMLLoader 这可以通过在外部控件中调用FXMLLoader::setClassLoader方法来完成。

在您的情况下:

FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("SliderVariable.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);

// set FXMLLoader's classloader!
fxmlLoader.setClassLoader(getClass().getClassLoader());

try {
    fxmlLoader.load();
} catch (IOException exception) { }

如果重试,您将获得两个控件作为自定义组件。

导入嵌套控件

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM