在JAR文件中加载时,JavaFX 2.2 Controller initialize()未被调用

时间:2013-02-15 17:25:48

标签: java javafx-2 javafx

背景:我已经使用JFXPanel创建了一个嵌入在Swing框架中的JavaFX应用程序。我一直在使用Eclipse作为IDE。 “主应用程序”是另一个类,它只用于创建一个类的实例,该类在实例化时扩展JFXPanel以加载我的.fxml文件。从Eclipse执行主类时,一切都很好,我的.fxml文件中指定的fx:controller调用了它的initialize()方法(我可以告诉它在加载时对UI做出的更改)并且没有问题

但是,当我将所有内容打包到JAR并尝试将我的JFXPanel扩展类添加到Swing JFrame实例时,它设法加载.fxml文件,只需读取图像,样式表等,以及其余的代码按预期运行,但从不调用fx:controller的{​​{1}}方法。我从jar内部或外部的其他类访问类没有问题,我甚至尝试设置一个ControllerFactory,它将返回Controller的一个实例,并尝试设置initialize()'的各种组合s类加载器并使用调用FXMLLoader的静态和非静态方法。结果始终相同:从IDE启动时它会起作用,但从我的打包jar启动时却不起作用。我知道jar没有丢失任何文件,因为就像我说的那样从Java代码中找到类没有问题,并且捆绑的fxml / css文件似乎正在加载,减去控制器问​​题。

之前有人遇到过此问题,或者想知道load()无法设置控制器可能会发生什么?这可能是某种错误吗?

3 个答案:

答案 0 :(得分:1)

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

使用以下代码解析我的.fxml文件。

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

要说这是你的错误的“原因”,我不确定,但这肯定让我困扰了一段时间,似乎是我的问题。

原始问题:Executable Jar limited to one window with JavaFX

答案 1 :(得分:0)

我无法解决这个问题。虽然fxml / css文件加载正常并且引用了正确的控制器类,但是一旦将所有内容打包到jar中,我仍然无法看到控制器类的initialize()方法被调用。

因为我唯一需要控制器的是获取fxml文件中定义的各种UI对象,以便我可以用它们进行真正的编程,我选择只创建一个递归搜索来查找这些单独的小部件他们的fxml ID [似乎首先查找'id'然后'fx:id'如果在场景树中找不到'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;
}

答案 2 :(得分:0)

我遇到了同样的问题,即从IDE调用<gateway>方法,而不是从(阴影)jar调用。

问题是我们使用的ProGuard配置为保留initialize()protected方法。但是,public方法已声明为initialize()。因此,它混淆了方法名称,JavaFX无法找到任何适当命名的方法,并且private从未被调用过。

要阻止ProGuard模糊JavaFX带注释的方法和字段,请将此规则包含在initialize()中:

proguard.conf

第一行将保留-keepattributes javafx.fxml.FXML -keepclassmembers class * { @javafx.fxml.FXML *; } 注释,另一个规则保留@FXML注释的类成员名称。