当您 运行 来自 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()
}
}
在过去的几天里,我一直在撕扯我的头发,试图到达圣杯: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()
}
}