2013-02-15 72 views
1

背景:我创建了一个使用JFXPanel嵌入Swing框架中的JavaFX应用程序。我一直在使用Eclipse作为IDE。 “主应用程序”是另一个类,它只用于创建一个扩展JFXPanel以在实例化时加载我的.fxml文件的类的实例。当从Eclipse执行主类时,一切都很好,我的.fxml文件中指定的fx:控制器调用了其方法initialize()(我可以通过它在加载时对UI进行的更改进行分析),并且没有任何问题。但是,当我将所有东西打包成一个JAR并尝试将我的JFXPanel扩展类添加到一个Swing JFrame实例时,它设法加载.fxml文件,只是精细读取图像,样式表等,而其余的该代码正常工作,但fx:controllerinitialize()方法从未被调用过。我没有问题从jar内部或外部的其他类访问类,我甚至尝试设置一个ControllerFactory,它将返回Controller的一个实例,并尝试各种组合设置FXMLLoader的类加载器并使用无论是调用load()的静态和非静态方法。结果总是相同的:从IDE启动时它将起作用,但在从我的打包jar启动时不起作用。我知道这个jar不会丢失任何文件,因为就像我说的那样,从Java代码中找到该类并没有问题,并且捆绑的fxml/css文件似乎加载正常,减去控制器问​​题。JavaFX 2.2在JAR文件中加载时未调用控制器initialize()

有人曾经遇到过这种情况,或者有什么想法可能会发生什么FXMLLoader未能设置控制器?这可能是某种错误吗?

+0

你的jar是如何部署的?对于JavaFX 2.2,由于FXML使用反射,FXML目前无法在未签名的webstart或applet中工作。我也相信,由于如何管理OSGI类加载(尽管我从未尝试过),可能需要进行一些调整以使JavaFX 2.2 FXML应用程序可以在OSGI环境中工作。您的Jar应该使用JavaFX部署工具打包,否则它可能找不到正确的运行时。也许其中一件事是你的问题。 – jewelsea 2013-05-01 21:09:34

回答

0

我无法来解决这个问题。当fxml/css文件加载正常并引用正确的控制器类时,我仍然无法看到控制器类的initialize()方法一旦被打包到jar中就会被调用。

由于我唯一需要的控制器是抓取fxml文件中定义的各种UI对象,以便我可以用它们进行真正的编程,我选择了创建递归搜索来查找这些单独的小部件通过他们的FXML ID [似乎查找“身份证”第一则“外汇:身份证”如果“身份证”找不到]在场景树..

//grabs fxml file relative to root of the jar 
FXMLLoader loader = new FXMLLoader(ClassLoader.getSystemClassLoader().getResource("app.fxml")); 
Parent javaFXRoot = (Parent) loader.load(); 

public Node findWidgetByID(String id, Parent javaFXRoot) 
{ 
    return findObject(root, id); 
} 

private Node findObject(Parent root, String id) 
{ 
    for (Node node : root.getChildrenUnmodifiable()) 
    { 
     if (node.getId() != null && node.getId().equals(id)) 
     { 
      return node; // found the node, return it 
     } 
     Node retValue = null; 
     if (node instanceof Parent) 
     { 
      retValue = findObject(((Parent) node), id); // recursive search 
     } 
     if (retValue != null) //if our node was found by the recursive search, return that 
     { 
      return retValue; 
     } 
    } 
    return null; 
} 
1

将我的JavaFX软件打包到.jar文件时,我遇到了类似的问题。原来这是一个关于相对路径的问题。你对IDE没有任何问题,但是当它在jar中编译时会遇到问题。

这是解决使用以下代码来调用我的.fxml文件。

getClass().getClassloader().getResource("/my/view/selector.fxml") 

,这不能不说是“理性”为你的错误,我不知道,但是这肯定难倒我了一会儿,似乎是相当多的问题,我有。

原题:Executable Jar limited to one window with JavaFX

+0

问题不在于查找fxml文件或jar中的任何内容,问题在于在加载fxml后控制器类的initialize方法未被调用。 fxml文件本身(和css)被发现并加载得很好。因为我只需要这个来获取对fxml中组件的引用以便进一步编码,所以我选择了创建一个“通过id查找小部件”的递归搜索方法来在场景的根目录上运行,以便根据它们的fxml来查找各种组件IDS。 – 2013-05-01 19:49:23

+0

我没有100%跟进,但我认为如果你用你所做的(显示一些代码)回答了这个问题,这将是很好的。这可能会有助于其他人看这个。 – blo0p3r 2013-05-01 19:59:23

0

我有同样的问题,其中initialize()方法是从IDE调用的,但不是来自(阴影)的jar。

问题是我们使用的ProGuard配置为保留protectedpublic方法。然而,initialize()方法被宣布为private。因此它混淆了方法名称,JavaFX找不到任何适当命名的方法,并且从未调用过initialize()

要混淆你的JavaFX注释的方法和字段停止ProGuard的,包括这个规则到您的proguard.conf

-keepattributes javafx.fxml.FXML 

-keepclassmembers class * { 
    @javafx.fxml.FXML *; 
} 

第一行会保持@FXML注释,其他规则保持@FXML注解的类成员名称。