94

我无法让 IntellJ 识别 JavaFX 包。使用 OpenJDK 11 的新 JavaFX 项目,在尝试构建项目时,IntelliJ 无法识别 JavaFX 包。

我已经openjfx:javafx-base-11从 Maven 存储库导入。

我查看了其他问题,解决方案似乎包括检查字节码是否处于正确的级别(我的是),以及项目语言是否正确(我的是)。

有人有想法么?

图 1

图二

图 3

编辑:

错误:

在此处输入图像描述

4

7 回答 7

159

正如评论中提到的,入门指南是从 Java 11 和 JavaFX 11 开始的地方。

像您在 Java 11 之前所做的那样工作的关键是要了解:

  • JavaFX 11 不再是 JDK 的一部分
  • 您可以以不同的方式获得它,作为 SDK 或作为常规依赖项(maven/gradle)。
  • 即使您的项目不是模块化的,您也需要将其包含到项目的模块路径中。

JavaFX 项目

如果您在 IntelliJ(没有 Maven 或 Gradle)中创建常规 JavaFX 默认项目,我建议您从此处下载 SDK 。请注意,也有 jmod,但对于非模块化项目,SDK 是首选。

这些是运行默认项目的简单步骤:

  1. 创建 JavaFX 项目
  2. 设置 JDK 11(指向你本地的 Java 11 版本)
  3. 将 JavaFX 11 SDK 添加为库。URL 可能类似于/Users/<user>/Downloads/javafx-sdk-11/lib/. 完成此操作后,您会注意到 JavaFX 类现在已在编辑器中识别。

JavaFX 11 项目

  1. 在运行默认项目之前,您只需将这些添加到 VM 选项中:

    --module-path /Users/<user>/Downloads/javafx-sdk-11/lib --add-modules=javafx.controls,javafx.fxml

马文

如果您使用 Maven 构建您的项目,请按照以下步骤操作:

  1. 使用 JavaFX 原型创建 Maven 项目
  2. 设置 JDK 11(指向你本地的 Java 11 版本)
  3. 添加 JavaFX 11 依赖项。

    <dependencies>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>11</version>
        </dependency>
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>11</version>
        </dependency>
    </dependencies>
    

完成此操作后,您会注意到 JavaFX 类现在已在编辑器中识别。

JavaFX 11 Maven 项目

您会注意到 Maven 为您管理所需的依赖项:它将为 javafx.controls 添加 javafx.base 和 javafx.graphics,但最重要的是,它将根据您的平台添加所需的分类器。就我而言,Mac。

这就是为什么你的 jarorg.openjfx:javafx-controls:11的,因为存在三个可能的分类器(windows、linux 和 mac 平台),它们包含所有类和本机实现。

如果您仍想转到 .m2 存储库并手动从那里获取依赖项,请确保选择正确的(例如.m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-mac.jar

  1. 用这里的那些替换默认的 Maven 插件。

  2. 运行mvn compile javafx:run,它应该可以工作。

Gradle 项目也有类似的工作,如在此处详细解释的那样。

编辑

提到的入门指南包含 IntelliJ 的更新文档和示例项目:

于 2018-09-23T20:49:32.677 回答
17

JavaFX 不再是 JDK 11 的一部分的问题。以下解决方案使用 IntelliJ 工作(尚未使用 NetBeans 尝试过):

  1. 添加 JavaFX 全局库作为依赖项:

    设置 -> 项目结构 -> 模块。在模块中转到 Dependencies 选项卡,然后单击添加“+”号 -> Library -> Java-> 从列表中选择 JavaFX,然后单击 Add Selected,然后单击 Apply settings。

  2. 右键单击 JavaFX 项目中的源文件 (src),然后创建一个新的 module-info.java 文件。在文件中写入以下代码:

    module YourProjectName { 
        requires javafx.fxml;
        requires javafx.controls;
        requires javafx.graphics;
        opens sample;
    }
    

    我向您保证,这两个步骤将解决您使用 JavaFX 的所有问题。

参考:The Learn Programming 频道制作了一个 You Tube 教程,将在 5 分钟内解释上述所有细节。我还建议观看它来解决您的问题: https ://www.youtube.com/watch?v=WtOgoomDewo

于 2019-04-25T12:20:42.207 回答
7

以上都不适合我。我花了太多时间来清除出现的其他错误。我发现这是最简单也是最好的方法。

这也适用于在 Jdk 11、12 和 OpenJdk12 上获取 JavaFx!

  • 该视频向您展示了 JavaFx Sdk 下载
  • 如何将其设置为全局库
  • 设置module-info.java(我更喜欢底部的)

module thisIsTheNameOfYourProject {
    requires javafx.fxml;
    requires javafx.controls;
    requires javafx.graphics;
    opens sample;
}

整个事情只花了我5分钟!

于 2019-04-26T07:56:57.197 回答
6

2020 年 12 月 14 日更新

Intellij 为 Idea 创建了一个新的 JavaFX 项目向导

强烈建议,如果您在使 JavaFX 项目工作时遇到问题,请使用新的 JavaFX 项目向导

  1. 使用向导创建一个新项目。
  2. 测试新项目是否有效。
  3. 将旧项目中的相关代码复制到新项目中。

新项目向导非常简单易用,可以在不到一分钟的时间内启动并运行一个有效的 JavaFX 项目。

向导生成的项目具有以下特点:

  1. 用于小型应用程序的简单工作示例代码。
  2. 使用 JavaFX 图形、控件、fxml。
  3. 配置 maven 或 gradle 项目以使用 JavaFX,并具有适当的 maven 工件依赖项以进行基本开发。
  4. 使用最新的、相当最新的 JavaFX 模块,并具有一致的版本(这是许多初学者通常不会做的事情)。
  5. 添加适用于基于 FXML 的 JavaFX 应用程序的 module-info.java 文件(如果您不使用 FXML,也可以使用)。
  6. 演示将 FXML 文件放置在资源目录中,并在运行时将其作为资源进行查找(这是很多很多初学者都会犯的错误)。
  7. 将 Controller 类与 Application 类正确分离(这也是许多初学者会犯的错误)。
  8. 演示基于 FXML 文件中的 id 正确使用 @FXML 注入(这也是许多初学者会出错的地方)。
  9. 不需要 openjfx JavaFX SDK 下载(因为 JavaFX 模块依赖是通过 maven 获取的)。
  10. 不需要手动设置 VM 参数来运行应用程序(因为适当的模块语句位于 module-info.java 文件中,而不是 VM 命令行中)。
  11. 允许直接从 IDE 执行和调试 JavaFX 应用程序。
  12. 包括 openjfx maven 插件。
    • 如果需要,您可以忽略它或将其从生成的项目文件中删除。

关于 openjfx-maven 插件的一些想法:

  • 对于大多数开发,我认为您不需要使用它。
    • 如果你不需要它,你可以从你的项目中删除它。
  • 执行应用程序不需要 openjfx maven 插件
    • 尽管如果您真的愿意,您可以使用它,但据我所知,它并没有比在 IDE 中直接执行提供任何优势。
  • 如果您希望这样做,openjfx maven 插件可用于构建基于 jlink 的分发。
  • openjfx maven 插件无法使用 打包您的应用程序jpackage,至少目前:

事先答复

此先前答案中的某些信息对于了解有关 Java 平台模块化和 JavaFX 的背景信息仍然有用。

快速总结,您可以执行以下任一操作:

  1. 在 José 的回答中通过--module-path和like包含 JavaFX 模块。--add-modules

或者

  1. 将 JavaFX 库添加到项目后(手动或通过 maven/gradle 导入),添加module-info.java与此答案中指定的文件类似的文件。(请注意,此解决方案使您的应用程序模块化,因此如果您使用其他库,您还需要在module-info.java文件中添加语句以要求它们的模块)。

这个答案是对何塞答案的补充。

情况是这样的:

  1. 您使用的是最新的 Java 版本,例如 13。
  2. 您有一个 JavaFX 应用程序作为 Maven 项目。
  3. 在您的 Maven 项目中,您按照 Jose 的回答配置了 JavaFX 插件并设置了 JavaFX 依赖项。
  4. 您转到扩展应用程序的主类的源代码,右键单击它并尝试运行它。
  5. IllegalAccessError尝试启动应用程序时,您会遇到一个“未命名的模块”。

IllegalAccessError尝试从 Intellij Idea 运行 JavaFX 应用程序时生成的堆栈跟踪摘录:

Exception in Application start method
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:567)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
    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:567)
    at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1051)
Caused by: java.lang.RuntimeException: Exception in Application start method
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
    at java.base/java.lang.Thread.run(Thread.java:830)
Caused by: java.lang.IllegalAccessError: class com.sun.javafx.fxml.FXMLLoaderHelper (in unnamed module @0x45069d0e) cannot access class com.sun.javafx.util.Utils (in module javafx.graphics) because module javafx.graphics does not export com.sun.javafx.util to unnamed module @0x45069d0e
    at com.sun.javafx.fxml.FXMLLoaderHelper.<clinit>(FXMLLoaderHelper.java:38)
    at javafx.fxml.FXMLLoader.<clinit>(FXMLLoader.java:2056)
    at org.jewelsea.demo.javafx.springboot.Main.start(Main.java:13)
    at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
    at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application org.jewelsea.demo.javafx.springboot.Main

好的,现在你有点卡住了,不知道发生了什么。

实际发生的事情是这样的:

  1. Maven 已为您的应用程序成功下载了 JavaFX 依赖项,因此您无需单独下载依赖项或安装 JavaFX SDK 或模块分发或类似的任何东西。
  2. Idea 已成功将模块作为依赖项导入到您的项目中,因此一切编译正常,所有代码完成,一切正常。

所以看起来一切都应该没问题。但是,当您运行应用程序时,JavaFX 模块中的代码在尝试使用反射来实例化应用程序类(调用启动时)和 FXML 控制器类(加载 FXML 时)的实例时会失败。如果没有一些帮助,这种反射的使用在某些情况下可能会失败,从而产生晦涩的IllegalAccessError. 这是由于 Java 模块系统安全功能不允许来自其他模块的代码在您的类上使用反射,除非您明确允许它(并且 JavaFX 应用程序启动器和 FXMLLoader 都需要在其当前实现中进行反射才能使它们起作用正确)。

这就是该问题的其他一些答案(参考module-info.java)出现的地方。

那么让我们来学习一下 Java 模块的速成课程:

关键部分是这样的:

4.9. 打开

如果我们需要允许私有类型的反射,但我们不想暴露所有代码,我们可以使用 opens 指令来暴露特定的包。

但请记住,这将向整个世界打开包,因此请确保这是您想要的:

module my.module { opens com.my.package; }

所以,也许你不想向全世界打开你的包裹,那么你可以这样做:

4.10。打开……到

好的,所以反射有时很棒,但我们仍然希望从封装中获得尽可能多的安全性。我们可以选择性地打开我们的包到预先批准的模块列表,在这种情况下,使用 opens...to 指令:

module my.module { 打开 com.my.package 到 moduleOne、moduleTwo 等;}

因此,您最终创建了一个 src/main/java/module-info.java 类,如下所示:

module org.jewelsea.demo.javafx.springboot {
    requires javafx.fxml;
    requires javafx.controls;
    requires javafx.graphics;
    opens org.jewelsea.demo.javafx.springboot to javafx.graphics,javafx.fxml;
}

包含 JavaFX Application 类和 JavaFX Controller 类的包的名称在哪里org.jewelsea.demo.javafx.springboot(将其替换为您的应用程序的适当包名称)。这告诉 Java 运行时,可以在包中的类javafx.graphicsjavafx.fxml调用对org.jewelsea.demo.javafx.springboot包中的类的反射。一旦完成,应用程序被编译并重新运行,一切都会正常工作IllegalAccessError,JavaFX 使用反射生成的将不再发生。

但是如果你不想创建一个 module-info.java 文件怎么办

如果不使用 IDE 顶部工具栏中的“运行”按钮直接运行您的应用程序类,您可以:

  1. 转到IDE一侧的Maven窗口。
  2. 选择 JavaFX maven 插件目标javafx.run
  3. 右键单击它并选择Run Maven BuildDebug...

然后应用程序将在没有module-info.java文件的情况下运行。我想这是因为 maven 插件足够智能,可以动态包含某种设置,即使没有module-info.java文件,JavaFX 类也可以反映应用程序,尽管我不知道这是如何实现的。

要将该设置转移到顶部工具栏中的“运行”按钮,请右键单击javafx.runMaven 目标并为目标选择选项Create Run/Debug Configuration。然后,您只需从顶部工具栏中选择 Run 即可执行 Maven 目标。

于 2019-09-11T23:29:13.747 回答
1

现在是 2021 年,JetBrains 更新了他们的 IDE。有关此错误消息的其他问题已关闭并指向此处。

Error: JavaFX runtime components are missing, and are required to run this application

如果您已遵循这些答案中的所有其他步骤(例如库、、、、--module-path版本--add-modules匹配 JDK 和 JavaFX),并且您仍然看到此编译错误,请确保您的运行/编译配置在 IntelliJ 中具有--module-path--add-modulesasVM Options而不是。Program Arguments

  1. 打开Run/Debug Configurations
  2. 打开Modify Options下拉菜单
  3. 点击Add VM Options
于 2021-11-22T06:35:02.557 回答
0

一个很好的解释可以在

https://edencoding.com/runtime-components-error/

包含

  1. 提供对模块的反射访问

  2. 授予对您的模块的其他访问权限

总而言之,我们需要在上述答案的基础上,将导出添加到您的模块定义中

module my.project {
    requires javafx.fxml;
    requires javafx.controls;
    opens my.project to javafx.graphics;
    exports my.project;
}
于 2021-04-04T12:20:51.150 回答
0

添加VM选项,(在运行配置中),这一行:

--module-path yourpathwheresdkislocated/lib --add-modules=javafx.controls,javafx.fxml 

如果你想从终端运行你的 jar 应用程序,把这个

java --module-path yourpathwheresdkislocated/lib --add-modules=javafx.controls,javafx.fxml -jar YourJar.jar 
于 2021-12-02T18:38:24.840 回答