当您 运行 来自 Gradle 项目的可执行文件时,在 JavaFX 中捆绑?

Bundle in JavaFX when you run the executable from a Gradle project?

在过去的几天里,我一直在撕扯我的头发,试图到达圣杯:Gradle + Java 11 + JavaFX + 写作我所有的应用程序和测试代码都在 Groovy 中,而不是 Java.

几个问题之一是 Groovy 2(甚至 Groovy 3)还不能处理 Java 9+ 模块,这将 排除在外。

但我已经成功地完成了一个 Gradle 项目,它不仅几乎成功地完成了所有事情,包括 "run" 任务(来自 "application" 插件)和 运行s 使用 TestFX 进行测试!这确实是在使用 Java 11、Groovy 2.5.9、JavaFX 13 等

它甚至会执行任务"installdist"(当包含在build.gradle中时)。这会生成一个带有 "lib" 目录的可执行文件,其中包含您需要独立 运行 的所有 jar(如任务 "assemble",只是未压缩)。

问题是,当我执行那个可执行文件时,我得到了现在经典的 "Error: JavaFX runtime components are missing, and are required to run this application"。仍然困惑为什么会发生这种情况,因为目录 [project dir]/build/install/GradleExp/lib 确实包含不少于 7 JavaFX .jars.

我想我已经用尽了尝试配置 Gradle 的方法:考虑到我正在使用 Groovy 作为应用程序和测试代码,我认为无法配置Gradle 项目让 "installdist" 生成一个准备就绪的 运行 Java 启用 FX 的可执行文件。但是...在 产生这个之后我可以做些什么吗,就像我可以 运行 以某种方式引入的命令一样JavaFX 文件和 link 它们在什么地方?即使这涉及 link 不优雅地访问某些 JavaFX jar 文件或位置?

或者我可以使用.../build/scripts 下的 "build" 任务生成的可执行 sh 脚本文件?这在定义 CLASSPATH:

...
CLASSPATH=$APP_HOME/lib/GradleExp-1.0.jar:
$APP_HOME/lib/commons-math3-3.6.1.jar:
$APP_HOME/lib/guava-27.0.1-jre.jar:
$APP_HOME/lib/javafx-fxml-13-linux.jar:
$APP_HOME/lib/javafx-controls-13-linux.jar:
$APP_HOME/lib/javafx-controls-13.jar:
$APP_HOME/lib/javafx-graphics-13-linux.jar:
$APP_HOME/lib/javafx-graphics-13.jar:
$APP_HOME/lib/javafx-base-13-linux.jar:
$APP_HOME/lib/javafx-base-13.jar:...

...当我尝试 运行 该脚本时,我得到:

mike@M17A /.../GradleExp/build/scripts $  ./GradleExp
Error: Could not find or load main class SceneSwitcher
Caused by: java.lang.ClassNotFoundException: SceneSwitcher

编辑
有趣的是:实际上那个脚本文件中的 APP_HOME 结果是 [project directory]/build.但是在那下面没有目录"lib"。有一个目录 "libs",其中恰好包含一个文件:GradleExp-1.0.jar,27 kB,无论如何想象都不是 "fat" jar。

我刚刚将 "lib" 目录从 "installdist" 任务复制到 /build,并且 运行 该脚本文件:同样,尽管有所有这些 JavaFX罐子现在可用,我再次得到 "Error: JavaFX runtime components are missing, and are required to run this application"。嗯...我还有很多东西要学

Slaw 和 cfrick 在他们的评论中回答了我的问题。我认为这可能对某些人有用。

如果您希望在 class 路径上使用 JavaFX 模块,则创建一个单独的主 class,它不会扩展 Application 并从 main方法。

cfrick 的示例精简工作 Gradle 项目是 here。我添加了以下行:

installDist{}

... 这使得一个新任务可用:./gradlew installdist 然后将在 build/install/.

下生成一个可执行文件

如果 cfrick 的 github 页面消失,build.gradle 是这样的:

plugins {
    id 'groovy'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
}

repositories {
    jcenter()
}

javafx {
    version = "11.0.2"
    modules = [ 'javafx.controls' ]
}

dependencies {
    implementation 'org.codehaus.groovy:groovy:3.+'
}

application {
    mainClassName = 'ofx.App'
}

installDist{} // my addition

和src/main/groovy/ofx/App.groovy是这样的:

package ofx

import javafx.application.Application
import javafx.scene.Scene
import javafx.scene.control.Label
import javafx.scene.layout.StackPane
import javafx.stage.Stage

class App {
    static void main(String[] args) {
        Application.launch(HelloFx, args)
    }
}

class HelloFx extends Application {

    @Override
    void start(Stage stage) {
        def javaVersion = System.getProperty("java.version")
        def javafxVersion = System.getProperty("javafx.version")
        Label l = new Label("Hello, JavaFX $javafxVersion, running on Java $javaVersion.")
        Scene scene = new Scene(new StackPane(l), 640, 480)
        stage.setScene(scene)
        stage.show()
    }

}