1

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

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

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

4

3 回答 3

1

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

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

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

要说这是你的错误的“原因”,我不确定,但这确实让我难过一段时间,似乎几乎是我遇到的问题。

原始问题:Executable Jar 仅限于一个带有 JavaFX 的窗口

于 2013-02-15T21:22:07.277 回答
0

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

由于我需要控制器的唯一事情是获取 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;
}
于 2013-05-01T20:48:39.400 回答
0

我在从 IDE 调用该方法时遇到了同样的问题initialize(),但不是从(阴影)jar 调用。

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

要阻止 ProGuard 混淆您的 JavaFX 注释方法和字段,请将此规则包含在您的proguard.conf:

-keepattributes javafx.fxml.FXML

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

第一行将保留@FXML注释,另一条规则保留带@FXML注释的类成员名称。

于 2017-06-15T17:20:28.503 回答