首页 > 解决方案 > 将 IntelliJ 中的 JavaFX 11 实现从“使用 IDE 中的 jvm 选项构建和运行”更改为“创建运行时映像”

问题描述

编辑#3(解决方案)

我没有使用任何建议的答案解决了这个问题。最后,我有一些文件夹和文件可以压缩和发送,不需要安装 java 并且可以通过双击 .bat 文件来运行。以下程序对我有用:

//Main start method
Parent root = FXMLLoader.load(new File("fxml/main.fxml").toURI().toURL());

//Other FXML loading operations
FXMLLoader loader = null;
try { loader = new FXMLLoader(new File("fxml/GRAPHISO_proof.fxml").toURI().toURL()); }
...

对于样式表:

scene.getStylesheets().add("file:///" + new File("css/text-field-red-border.css").getAbsolutePath().replace('\\', '/'));
module XYZ {
    requires javafx.controls;
    requires javafx.graphics;
    requires java.desktop;
    requires javafx.fxml;
    requires javafx.base;

    opens main.controller to javafx.fxml;
    //Open ALL controller-modules (all of my modules have a controller-submodule, e.g. main/controller, dlog/controller, graphiso/controller, ...) to javafx.fxml
    //...

    exports main;
}
buildscript {
    repositories {
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath 'org.openjfx:javafx-plugin:0.0.8'
        classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
    }
}

plugins {
    id 'java'
    id 'org.beryx.jlink' version '2.19.0'
}

apply plugin: 'org.openjfx.javafxplugin'
apply plugin: 'com.github.johnrengelman.shadow'

group 'org.example.abc'
version '1.0'

sourceCompatibility = 1.14

repositories {
    mavenCentral()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

javafx {
    sdk = 'C:\\Program Files\\Java\\javafx-sdk-14.0.1'
    modules = [ 'javafx.controls', 'javafx.fxml', 'javafx.base' ]
}

jlink {
    mainClassName = 'main.AppLauncher'
    launcher {
        name = 'Whatever you want as name'
    }
}

tasks.jlink.doLast {
    copy {
        from('src/main/resources')
        into("$buildDir/image/bin")
    }
    copy {
        from 'C:\\Program Files\\Java\\javafx-sdk-14.0.1\\bin\\glass.dll',
             'C:\\Program Files\\Java\\javafx-sdk-14.0.1\\bin\\javafx_font.dll',
             'C:\\Program Files\\Java\\javafx-sdk-14.0.1\\bin\\prism_d3d.dll',
             'C:\\Program Files\\Java\\javafx-sdk-14.0.1\\bin\\prism_sw.dll'
        into("$buildDir/image/bin")
    }
}

请注意我是如何在 tasks.jlink.doLast 中包含一些 dll 文件的。没有它们,程序会不断崩溃并引用 QuantumRenderer。


原始问题

我正在尝试通过仅使用 IntelliJ 中的“运行配置”功能从我在 JavaFX 11 中实现的项目创建运行时映像。在我看来,这里的一个大问题是我对 maven/gradle 的了解几乎不存在,而这些构建工具对于这一步至关重要。

在里面C:\Program Files\Java我已经安装了:

我将 IntellJ 的“运行配置”中的 VM 选项配置为--module-path "C:\Program Files\Java\javafx-sdk-11.0.2\lib" --add-modules javafx.controls,javafx.fxml并将主类设置为“main.Main”。

我的项目结构如下所示:项目文件夹结构

突出显示的 Main.java 是一个常用的 Main 文件(扩展 Application,在 main 内部调用launch (args))。它可以加载位于其他包中的其他窗口。它不是一个启动器文​​件,它不扩展应用程序并调用实际的主文件(正如一些 gradle-building 解决方案所建议的那样)。

最初,我试图获得一个 .jar 文件,它可以在 Windows 和 Linux 上运行而无需任何其他参数。经过一番阅读,我认为这不是一个干净的解决方案,并且许多消息来源指出,在现代解决方案中,.jar 文件将被放在一起并附带一个包含所有必要参数的 .bat/.sh 文件。

我的问题是:如何最好地进行以及需要哪些配置/附加文件才能将这个“click-to-run-inside-IDE”项目转换为可以通过电子邮件或类似方式共享的“独立应用程序” ?

我试图通过 IntelliJ 创建一个新的 gradle 项目(遵循https://openjfx.io/openjfx-docs)并将源文件复制粘贴到 src/main/java 中。然后我尝试了提供的 build.gradle-file 并且 - 之后没有工作 - 进行了各种博客/论坛/等建议的一些更改。他们都不允许我通过 IntelliJ 或命令行运行项目。

这些方法中的大多数让我构建项目,但是当尝试使用“gradlew run”或调用“java -jar file.jar”运行时,由于类异常或说我仍然缺少 javafx 模块,我收到错误消息。我还尝试了一种将我当前的项目转换为 gradle-project 的方法,但这甚至不允许我在之后构建项目。


编辑 #1 (JPackageScriptFX)

我查看了 JPackageScriptFX 链接。现在我得到了一个mvn clean install可以在我的机器上运行的安装程序(使用 ),但是在运行生成的可执行文件时,我收到一条错误消息,上面写着“无法启动 JVM”。

到目前为止我所做的是:

我的配置文件:


编辑#2

我尝试--runtime-image target/java-runtime ^从 build_app.bat 文件中的 jpackage 参数中删除,以便让 jpackage 决定要包含的内容。这增加了安装程序的文件大小(如预期的那样),但在尝试执行生成的程序时会导致相同的错误。

我还下载了 JMOD 文件,并在 build_app.bat 中的 jlink 任务中使用了它们,如此处所示

所以我换成--add-modules %detected_modules%,%manual_modules% ^

--module-path "C:\Program Files\Java\javafx-jmods-11.0.2" --add-modules %detected_modules%,%manual_modules%,javafx.controls,javafx.fxml

这产生了另一个运行良好的安装程序,并且其生成的程序引发了相同的错误。

标签: javamavengradleintellij-ideajavafx

解决方案


好吧,我将尝试展示如何仅使用jlink来实现这一点。假设我们在目录“C:\Users\Alexiy\IdeaProjects\AnotherBuildTool\rundir”中有一个示例项目。它的结构是:

/rundir
--classes [compilation output]
--source  [source code]
--images  [runtime image output]

我有一个类'source\io\github\alexiyorlov\calculator\Program.java':

package io.github.alexiyorlov.calculator;

import javafx.application.Application;
import javafx.stage.Stage;
import java.nio.file.Path;
public class Program extends Application {

   @Override
   public void start(Stage primaryStage) throws Exception {
       System.out.println("I'm a simple application");
       primaryStage.show();
   }
}

还有一个合适的'source\module-info.java':

module io.github.alexiyorlov{
   requires javafx.controls;
   requires javafx.graphics;
   exports io.github.alexiyorlov.calculator;
}

如果我想以此制作运行时映像,jlink命令的语法将如下所示:

jlink --launcher [启动脚本的名称]=[对主类的引用] --module-path '[项目依赖jar的分隔列表+编译输出目录]' --add-modules [我的模块引用] -- compress=2 --output [生成的运行时映像的目录]

因此,对于我的示例项目,它解析为以下命令:

jlink 
--launcher launch=io.github.alexiyorlov/io.github.alexiyorlov.calculator.Program 
--module-path 'C:\Users\Alexiy\.m2\repository\org\openjfx\javafx-controls\11.0.2\javafx-controls-11.0.2-win.jar;C:\Users\Alexiy\.m2\repository\org\junit\jupiter\junit-jupiter-engine\5.7.0-M1\junit-jupiter-engine-5.7.0-M1.jar;C:\Users\Alexiy\.m2\repository\org\openjfx\javafx-base\11.0.2\javafx-base-11.0.2.jar;C:\Users\Alexiy\.m2\repository\org\openjfx\javafx-base\11.0.2\javafx-base-11.0.2-win.jar;C:\Users\Alexiy\.m2\repository\org\openjfx\javafx-graphics\11.0.2\javafx-graphics-11.0.2.jar;C:\Users\Alexiy\.m2\repository\dev\buildtool\json-tools\0.1.0\json-tools-0.1.0.jar;C:\Users\Alexiy\IdeaProjects\AnotherBuildTool\rundir\org\openjfx\javafx\11.0.2\javafx-11.0.2/.jar;C:\Users\Alexiy\.m2\repository\org\openjfx\javafx-controls\11.0.2\javafx-controls-11.0.2.jar;C:\Users\Alexiy\.m2\repository\org\openjfx\javafx-graphics\11.0.2\javafx-graphics-11.0.2-win.jar;C:\Users\Alexiy\IdeaProjects\AnotherBuildTool\rundir/classes' 
--add-modules io.github.alexiyorlov 
--compress=2 
--output .\images\0.0.1

它将使用启动脚本“0.0.1\bin\launch”在目录“images\0.0.1”中创建一个图像。

请注意,我使用了一种自动方式来获取 --module-path 的正确参数;确保在其中包含类输出目录。

--add-modules 指定要包含的应用程序的哪些模块。

--output 指定一个目录来放置图像的所有文件。

--launcher 指定启动脚本的名称以及在“=”之后对主类的正确引用。

--compress=2 使其对图像应用 ZIP 压缩。

随时向我索取更多信息。


推荐阅读