Java 场景生成器嵌套自定义节点
我似乎在Scene Builder 8.4.1中遇到了一个相当严重的错误,其他人以前在不同版本中遇到过这个错误(请参见链接)。错误在于,当我尝试从jar文件导入一个自定义节点,而该节点又包含其他自定义节点时,只会找到嵌套的节点。也就是说,找不到外部节点 所以我想知道。是否有人知道Scene Builder的稳定版本在更新版本的java(8、9或10,如果还没有)中没有这个bug(最好没有其他严重的bug)?我还希望有一个安装向导,它将为我提供一个exe应用程序,而不是一个可运行的jar,以便更好地与我的IDE集成。如果不存在这种情况,您认为有经验的场景构建者推荐我做什么?我是否应该使所有fxml文档不包含嵌套节点,并在以后手动添加它们 谢谢你的帮助Java 场景生成器嵌套自定义节点,java,javafx,fxml,scenebuilder,Java,Javafx,Fxml,Scenebuilder,我似乎在Scene Builder 8.4.1中遇到了一个相当严重的错误,其他人以前在不同版本中遇到过这个错误(请参见链接)。错误在于,当我尝试从jar文件导入一个自定义节点,而该节点又包含其他自定义节点时,只会找到嵌套的节点。也就是说,找不到外部节点 所以我想知道。是否有人知道Scene Builder的稳定版本在更新版本的java(8、9或10,如果还没有)中没有这个bug(最好没有其他严重的bug)?我还希望有一个安装向导,它将为我提供一个exe应用程序,而不是一个可运行的jar,以便更好
编辑:可以找到所有源文件。请注意,外部容器是SliderVariable,内部容器是InfoIcon。您可以在同一个jar中嵌套两个或多个自定义控件,这将在IDE或命令行中正常运行 但是,如果从场景生成器导入该jar,如果某些自定义控件依赖于其他控件,则它们可能无法导入 这是有原因的,最好的是,还有一个简单的解决方案 如何导入自定义控件? 如果查看场景生成器,要导入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
}
因此,这基本上解释了为什么嵌套控件不被导入:内部控件事先在类路径中不可用
可能的解决方案
显然,您可以分别绑定这两个控件,首先导入InfoIcon
控件,然后只导入SliderVariable
控件。但是,如果您想在单个依赖项中分发这些控件,这可能会有问题
最佳解决方案
那么,如果内部控件和外部控件在同一个jar中,我们如何在运行时使它们可用呢
这是通过将此外部控制类的类加载器传递给fxmloader
来完成的。这可以通过调用外部控件中的fxmloader::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) { }
如果重试,则两个控件都可以作为自定义组件使用
这对我很有用。。。但它需要一些调整。你能发布一些我们可以复制的代码吗?我能在几个小时内完成。但是如果你查看我们一周前的聊天,我已经链接了一个罐子,如果你愿意,你可以尝试一下。我做了,但它不起作用。尽可能发布代码,我来看看。@JoséPereda现在您可以在提供的链接中找到源文件。这很有效!这给我带来了很多麻烦,最后,它成功了!这个评论是对你答案的赞扬。非常感谢。
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) { }