当您从 Gradle 项目运行可执行文件时在 JavaFX 中捆绑? [英] Bundle in JavaFX when you run the executable from a Gradle project?

查看:15
本文介绍了当您从 Gradle 项目运行可执行文件时在 JavaFX 中捆绑?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在过去的几天里,我一直在努力达到圣杯:Gradle + Java 11 + JavaFX + 用 Groovy 而不是 Java 编写我的所有应用程序和测试代码.

Over the past few days I've been tearing what's left of my hair out trying to get to the Holy Grail: Gradle + Java 11 + JavaFX + writing all my app and testing code in Groovy, not Java.

几个问题之一是 Groovy 2(甚至 Groovy 3)还不能处理 Java 9+ 模块,它规定 一个聪明的解决方案出来.

One of several problems is that Groovy 2 (even Groovy 3) can't yet cope with Java 9+ modules, which rules one clever solution out.

但我已经设法将 Gradle 项目组合在一起,它不仅成功地完成了几乎所有事情,包括运行"任务(来自应用程序"插件),并且使用 TestFX 运行测试!这确实是使用 Java 11、Groovy 2.5.9、JavaFX 13 等.

But I have managed to get a Gradle project together which not only does virtually everything successfully, including the "run" task (from the "application" plugin), and runs tests using TestFX! This is indeed using Java 11, Groovy 2.5.9, JavaFX 13, etc.

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

It will even execute the task "installdist" (when included in build.gradle). That produces an executable with a "lib" directory full of all the jars you need to run independently (like task "assemble", only not compressed).

问题是,当我执行该可执行文件时,我得到了现在经典的错误:缺少 JavaFX 运行时组件,需要运行此应用程序".仍然困惑为什么会发生这种情况,因为目录 [project dir]/build/install/GradleExp/lib 确实包含不少于 7 个 JavaFX .jar.

The trouble is, when I execute that executable I get the by now classic "Error: JavaFX runtime components are missing, and are required to run this application". Still confused why that happens, as the directory [project dir]/build/install/GradleExp/lib does indeed contain no fewer than 7 JavaFX .jars.

我想我已经用尽了我可以做的常规配置 Gradle 的尝试:鉴于我正在使用 Groovy 进行应用程序和测试代码,我认为无法配置 Gradle 项目以获取installdist"来生成一个可立即运行的启用 JavaFX 的可执行文件.但是……我可以在之后做些什么,比如我可以运行的一些命令以某种方式引入JavaFX文件并将它们链接起来?即使这涉及不雅地链接到某些 JavaFX jar 文件或位置?

I think I've exhausted what I can do trying to configure Gradle conventionally: given that I'm using Groovy for app and testing code I don't think it's possible to configure the Gradle project to get "installdist" to produce a ready-to-run JavaFX-enabled executable. But... is there something I can do after having produced this, like some command I could run that would somehow bring in the JavaFX files and link them in? Even if this involves linking inelegantly to some JavaFX jar file(s) or locations?

或者我可以在 .../build/scripts 下使用由构建"任务生成的可执行 sh 脚本文件?在定义 CLASSPATH 时,这会在上述 7 个 JavaFX .jar 文件中绑定:

Or maybe I could use the executable sh script file generated by the "build" task under .../build/scripts ? This ropes in the above-mentioned 7 JavaFX .jar files at the start when defining the 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:...

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

... when I try to run that script I get:

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

编辑
这是一件有趣的事情:实际上,该脚本文件中的 APP_HOME 原来是 [项目目录]/build.但在那之下没有目录lib".有一个目录libs",它只包含一个文件:GradleExp-1.0.jar,27 kB,不是任何想象中的胖"jar.

edit
Here's a funny thing: in fact APP_HOME in that script file turns out to be [project directory]/build. But under that there is no directory "lib". There is a directory "libs" which contains precisely one file: GradleExp-1.0.jar, 27 kB, not a "fat" jar by any stretch of the imagination.

我只是将lib"目录从installdist"任务复制到/build,并运行该脚本文件:再次,尽管现在所有这些JavaFX jars都可用,但我再次得到错误:JavaFX运行时缺少组件,运行此应用程序需要这些组件".嗯……我有很多东西要学.

I just copied the "lib" directory from the "installdist" task up to /build, and ran that script file: again, despite having all those JavaFX jars now available, I again get "Error: JavaFX runtime components are missing, and are required to run this application". Hmmm... I have much to learn.

推荐答案

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

Slaw and cfrick came up with the answer to my question in their comments. I thought this might come in useful for some.

如果你想在类路径上使用 JavaFX 模块,那么创建一个单独的主类,它不扩展 Application 并调用 Application.launch(YourApp.class, args) 来自 main 方法.

If you want the JavaFX modules on the class-path then create a separate main class which does not extend Application and invoke Application.launch(YourApp.class, args) from the main method.

cfrick 的精简工作 Gradle 项目示例位于此处.我添加了以下行:

cfrick's example stripped-down working Gradle project is here. I added the following line:

installDist{}

...这使得一个新任务可用:./gradlew installdist 然后将在 build/install/下生成一个可执行文件.

... this makes a new task available: ./gradlew installdist will then produce an executable under build/install/.

万一cfrick的github页面消失了,build.gradle是这样的:

In case cfrick's github page goes away, build.gradle is like this:

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 是这样的:

and src/main/groovy/ofx/App.groovy is like this:

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()
    }

}

这篇关于当您从 Gradle 项目运行可执行文件时在 JavaFX 中捆绑?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆