当您从Gradle项目运行可执行文件时,是否绑定JavaFX?

当您从Gradle项目运行可执行文件时,是否绑定JavaFX?,gradle,javafx,groovy,java-11,Gradle,Javafx,Groovy,Java 11,在过去的几天里,我一直在绞尽脑汁试图达到圣杯:Gradle+Java11+JavaFX+用Groovy而不是Java编写我所有的应用程序和测试代码 其中一个问题是Groovy2(甚至Groovy3)还不能处理Java9+模块,这就排除了这一点 但是我成功地完成了一个Gradle项目,它不仅成功地完成了几乎所有的事情,包括“运行”任务(来自“应用程序”插件),还使用TestFX运行测试!这实际上是在使用Java11、Groovy2.5.9、JavaFX13等 它甚至会执行任务“installdis

在过去的几天里,我一直在绞尽脑汁试图达到圣杯:Gradle+Java11+JavaFX+用Groovy而不是Java编写我所有的应用程序和测试代码

其中一个问题是Groovy2(甚至Groovy3)还不能处理Java9+模块,这就排除了这一点

但是我成功地完成了一个Gradle项目,它不仅成功地完成了几乎所有的事情,包括“运行”任务(来自“应用程序”插件),还使用TestFX运行测试!这实际上是在使用Java11、Groovy2.5.9、JavaFX13等

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

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

我想我已经用尽了常规配置Gradle所能做的:鉴于我正在使用Groovy for app和测试代码,我认为不可能将Gradle项目配置为获得“installdist”以生成一个支持JavaFX的可执行文件。但是在生成这个文件之后,我是否可以做一些事情,比如我可以运行一些命令,以某种方式引入JavaFX文件并将它们链接进来?即使这涉及到不雅观地链接到一些JavaFXJAR文件或位置

或者我可以使用由…/build/scripts下的“build”任务生成的可执行sh脚本文件?在定义类路径时,这将在开始时插入上述7个JavaFX.jar文件:

...
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,27kb,不是想象中的“胖”jar


我刚刚将“installdist”任务中的“lib”目录复制到/build,并运行了该脚本文件:再次,尽管现在所有这些javafxjar都可用,但我再次得到“错误:JavaFX运行时组件丢失,并且需要运行该应用程序”。六羟甲基三聚氰胺六甲醚。。。我有很多东西要学。

斯拉夫和cfrick在他们的评论中给出了我问题的答案。我想这可能对一些人有用

如果希望类路径上有JavaFX模块,则创建一个单独的主类,该主类不扩展
Application
,并从
main
方法调用
Application.launch(YourApp.class,args)

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

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

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

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

}

如果(1)您将JavaFX模块放在类路径上,(2)您的主类是
JavaFX.application.application
的子类,那么这可能是问题的根源。当主类是
应用程序的子类时,则
javafx.graphics
模块必须位于模块路径上。这是JavaFX的特殊启动处理目前如何实现的结果。因此,如果您希望类路径上的JavaFX模块,那么创建一个独立的主类,该类不扩展
应用程序
,并从主方法调用
应用程序.launch(YourApp.class,args)
。我试图为自己组合一个示例,但遇到了不同的问题,@Slaw的注释修复了这些问题。我的示例项目非常感谢这两者。为了未来的用户,也许你们中的一位愿意回答这个问题?好吧,请继续。