使用 gradle 6.3、OpenJDK 14 和 OpenJFX 14 部署 JavaFX 应用程序

Deploy JavaFX application using gradle 6.3, OpenJDK 14 and OpenJFX 14

我正在使用 gradle 6.3、OpenJDK 14 和 OpenJFX 14 以及 IntelliJ 开发 JavaFX 应用程序,我想部署它(创建一个 exe 文件)。

我曾经在 Netbeans 11 下使用 JDK 8 制作 JavaFX 应用程序,过程很简单:

  1. 申请
  2. 清理并构建
  3. 在 dist 文件夹中寻找 jar(当我点击它时它运行良好)
  4. 使用 Launch4j 将其转换为 exe
  5. 瞧!

因为我正在迁移到 OpenJDK 14,所以我想确保我可以部署我正在制作的应用程序,所以我创建了一个应用程序,当我 运行 它时一切正常(在智能)。我看到了一些关于如何使用 gradle 部署 javafx 应用程序的教程,我想到了这个过程:

  1. 在 gradle window(在屏幕的右上角),点击 distribution > distZip
  2. 在build\distibutions中查找生成的ZIP文件并解压
  3. 你会找到一个binlib 文件夹:在 bin 文件夹中,我找到了我项目的 .bat 文件和单击它时,我的应用程序启动并且一切正常。在 lib 文件夹中,我找到了我在我的项目中使用的所有 jar 文件加上我的 {project-name}.jar ,当我点击没有任何反应。

我尝试使用命令行 运行 它,这是我得到的结果:

    C:\Users\Admin\Documents\SmartDoc\build\distributions\SmartDoc-1.0\SmartDoc-1.0\lib>java -jar SmartDoc-1.0.jar
Table PATIENT created successfully !
Table DOSSIER_MEDICAL created successfully !
Table ORDONNANCE created successfully !
Table RENDEZ_VOUS created successfully !
Table SALLE_ATTENTE created successfully !
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
        at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
        at com.sun.javafx.application.LauncherImpl.lambda$launchApplication(LauncherImpl.java:195)
        at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: javafx.fxml.LoadException:
file:/C:/Users/Admin/Documents/SmartDoc/build/distributions/SmartDoc-1.0/SmartDoc-1.0/lib/SmartDoc-1.0.jar!/main.fxml:27

    at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2625)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2603)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3237)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3194)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3163)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3136)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3113)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3106)
    at com.smartdoc.gui.Launch.start(Launch.java:27)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1(LauncherImpl.java:846)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait(PlatformImpl.java:455)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:427)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$runLoop(WinApplication.java:174)
    ... 1 more
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
        at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:262)
        at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:54)
        at javafx.fxml.FXMLLoader$Element.applyProperty(FXMLLoader.java:520)
        at javafx.fxml.FXMLLoader$Element.processValue(FXMLLoader.java:370)
        at javafx.fxml.FXMLLoader$Element.processPropertyAttribute(FXMLLoader.java:332)
        at javafx.fxml.FXMLLoader$Element.processInstancePropertyAttributes(FXMLLoader.java:242)
        at javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:775)
        at javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2838)
        at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2557)
        ... 17 more
Caused by: java.lang.reflect.InvocationTargetException
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at com.sun.javafx.fxml.ModuleHelper.invoke(ModuleHelper.java:100)
        at com.sun.javafx.fxml.BeanAdapter.put(BeanAdapter.java:258)
        ... 25 more
Caused by: java.lang.UnsupportedOperationException: Cannot resolve 'fa-user-plus'
        at org.kordamp.ikonli.javafx.IkonResolver.resolveIkonHandler(IkonResolver.java:62)
        at org.kordamp.ikonli.javafx.FontIcon.setIconLiteral(FontIcon.java:239)
        ... 31 more

前 5 行是应用程序创建 derby 数据库的结果(完美运行),但是当涉及到 运行 应用程序时,我遇到了一些异常。 我也试过 运行 --module-path "C:\Program Files\Java\javafx-sdk-14.0.1\lib" --add-modules javafx.controls,javafx.fxml,javafx.base,javafx.graphics 但我得到了同样的例外。

我知道其中 none 3 个解决方案:

  1. 解决这个异常
  2. 尝试将 .bat 文件转换为 .exe 文件
  3. 一个新的解决方案

编辑: build.gradle 文件:

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

group 'com.smartdoc'
version '1.0'

repositories {
    mavenCentral()
}

dependencies {
    compile 'com.calendarfx:calendar:11.8.3'
    compile 'com.calendarfx:view:11.8.3'
    compile 'org.kordamp.ikonli:ikonli-core:11.4.0'
    compile 'org.kordamp.ikonli:ikonli-javafx:11.4.0'
    compile 'org.kordamp.ikonli:ikonli-fontawesome-pack:11.4.0'
    compile 'com.jfoenix:jfoenix:9.0.9'
    compile group: 'org.apache.derby', name: 'derby', version: '10.15.2.0'
    compile group: 'org.apache.derby', name: 'derbyclient', version: '10.15.2.0'
    compile group: 'org.apache.derby', name: 'derbynet', version: '10.15.2.0'

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

javafx {
    version = "14.0.1"
    modules = ['javafx.controls','javafx.fxml']
}

mainClassName = "$moduleName/com.smartdoc.Main"

jar {
    manifest {
        attributes "Main-Class": "$mainClassName"
    }

    from {
        configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

感谢您的帮助!

更新 1: 制作工作 .jar 文件

所以我尝试了一些解决方案来使我的 .jar 文件正常工作,我终于找到了一个:

  1. 添加到您的 build.gradle 的顶部:
buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.github.jengelman.gradle.plugins:shadow:5.2.0'
    }
}

plugins {
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.8'
    id 'com.github.johnrengelman.shadow' version '5.2.0'
}

apply plugin : 'com.github.johnrengelman.shadow'

(如你所见,我使用了 Gradle Shadow Plugin

  1. 在gradlewindow(intelliJIDE右上角),点击distribution > shadowDistZip
  2. 转到build\distributions,你会找到一个ZIP文件({projectName}-shadow-{version}),解压它。
  3. 打开文件夹,你会发现binlib文件夹,进入lib jar 的文件夹。
  4. 您会发现您的 .jar 可以像您期望的那样工作。

我还在研究如何制作.exe,所以如果有人有建议,欢迎!

更新 2: 使用 Launch4j 制作 .exe 文件

我终于设法从我之前创建的 jar 文件创建了一个 .exe 文件:我使用了 Launch4j(是的,它适用于 Java > 11).以下是简单的步骤:

  1. 首先下载 Launch4j 并安装它(不要 运行 它,它不会工作)
  2. 转到 Launch4j 文件,您将看到一个 launch4j.jar 文件,运行 它和 select 基本选项卡
  3. Select保存输出的路径(确保你在最后写.exe)
  4. Select 你的 .jar 文件所在的路径

  1. 现在转到 JRE 选项卡,在 Min JRE 版本中选择 11.0.1 以确保它仅以 Java > 11,并在 Max JRE 版本中选择您想要的最大 Java 版本(在我的例子中,最后一个版本是 14.0.1

  1. 现在点击顶部的齿轮,将配置文件保存到任何你想要的地方,瞧!您的 .exe 文件应该 运行ning 现在完全没问题了。

P.S.: 您可以使用 Launch4j 添加图标、清单文件和许多其他内容,我只是解释了有史以来最简单的示例,以便你们可以制作成功了,剩下的就看你了:)

如果有其他解决方案,请与我们分享,很多人都在为 JDK 14 的可执行文件而苦恼。

谢谢!