IntelliJ 无法使用 OpenJDK 11 识别 JavaFX 11

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/52467561/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:27:57  来源:igfitidea点击:

IntelliJ can't recognize JavaFX 11 with OpenJDK 11

javaintellij-ideajavafxjava-11javafx-11

提问by AlwaysNeedingHelp

I'm having trouble getting IntellJ to recognize JavaFX packages. With a new JavaFX project, with OpenJDK 11, when trying to build the project, IntelliJ can't recognize the JavaFX packages.

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

I've imported openjfx:javafx-base-11from the Maven repo.

我是openjfx:javafx-base-11从 Maven 仓库导入的。

I've looked at other questions and the solutions seem to range from checking that the bytecode is at the right level (mine is), and that the project language is correct (mine is).

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

Anyone have any ideas?

谁有想法?

pic 1

图1

pic 2

图2

pic 3

图3

Edit:

编辑:

Error:

错误:

enter image description here

在此处输入图片说明

采纳答案by José Pereda

As mentioned in the comments, the Starting Guideis the place to start with Java 11 and JavaFX 11.

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

The key to work as you did before Java 11 is to understand that:

像在 Java 11 之前一样工作的关键是要了解:

  • JavaFX 11 is not part of the JDK anymore
  • You can get it in different flavors, either as an SDK or as regular dependencies (maven/gradle).
  • You will need to include it to the module path of your project, even if your project is not modular.
  • JavaFX 11 不再是 JDK 的一部分
  • 您可以以不同的形式获取它,作为 SDK 或常规依赖项(maven/gradle)。
  • 即使您的项目不是模块化的,您也需要将其包含在项目的模块路径中。

JavaFX project

JavaFX 项目

If you create a regular JavaFX default project in IntelliJ (without Maven or Gradle) I'd suggest you download the SDK from here. Note that there are jmods as well, but for a non modular project the SDK is preferred.

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

These are the easy steps to run the default project:

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

  1. Create a JavaFX project
  2. Set JDK 11 (point to your local Java 11 version)
  3. Add the JavaFX 11 SDK as a library. The URL could be something like /Users/<user>/Downloads/javafx-sdk-11/lib/. Once you do this you will notice that the JavaFX classes are now recognized in the editor.
  1. 创建 JavaFX 项目
  2. 设置 JDK 11(指向您本地的 Java 11 版本)
  3. 添加 JavaFX 11 SDK 作为库。URL 可能类似于/Users/<user>/Downloads/javafx-sdk-11/lib/. 执行此操作后,您会注意到现在可以在编辑器中识别 JavaFX 类。

JavaFX 11 Project

JavaFX 11 项目

  1. Before you run the default project, you just need to add these to the VM options:

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

  2. Run

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

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

Maven

马文

If you use Maven to build your project, follow these steps:

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

  1. Create a Maven project with JavaFX archetype
  2. Set JDK 11 (point to your local Java 11 version)
  3. Add the JavaFX 11 dependencies.

    <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>
    
  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>
    

Once you do this you will notice that the JavaFX classes are now recognized in the editor.

执行此操作后,您会注意到现在可以在编辑器中识别 JavaFX 类。

JavaFX 11 Maven project

JavaFX 11 Maven 项目

You will notice that Maven manages the required dependencies for you: it will add javafx.base and javafx.graphics for javafx.controls, but most important, it will add the required classifierbased on your platform. In my case, Mac.

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

This is why your jars org.openjfx:javafx-controls:11are empty, because there are three possible classifiers (windows, linux and mac platforms), that contain all the classes and the native implementation.

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

In case you still want to go to your .m2 repo and take the dependencies from there manually, make sure you pick the right one (for instance .m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-mac.jar)

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

  1. Replace default maven plugins with those from here.

  2. Run mvn compile javafx:run, and it should work.

  1. 这里的插件替换默认的 maven 插件。

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

Similar works as well for Gradle projects, as explained in detail here.

类似的工作也适用于 Gradle 项目,详见此处

EDIT

编辑

The mentioned Getting Started guide contains updated documentationand sample projects for IntelliJ:

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

回答by Coder992

The issue that JavaFX is no longer part of JDK 11. The following solution works using IntelliJ (haven't tried it with NetBeans):

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

  1. Add JavaFX Global Library as a dependency:

    Settings -> Project Structure -> Module. In module go to the Dependencies tab, and click the add "+" sign -> Library -> Java-> choose JavaFX from the list and click Add Selected, then Apply settings.

  2. Right click source file (src) in your JavaFX project, and create a new module-info.java file. Inside the file write the following code :

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

    These 2 steps will solve all your issues with JavaFX, I assure you.

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

    设置 -> 项目结构 -> 模块。在模块中,转到依赖项选项卡,然后单击添加“+”号 -> 库 -> Java-> 从列表中选择 JavaFX 并单击添加选定项,然后单击应用设置。

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

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

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

Reference : There's a You Tube tutorial made by The Learn Programming channel, will explain all the details above in just 5 minutes. I also recommend watching it to solve your problem: https://www.youtube.com/watch?v=WtOgoomDewo

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

回答by Yo Apps

None of the above worked for me. I spent too much time clearing other errors that came up. I found this to be the easiest and the best way.

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

This works for getting JavaFx on Jdk 11, 12 & on OpenJdk12 too!

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

  • The Video shows you the JavaFx Sdk download
  • How to set it as a Global Library
  • Set the module-info.java(i prefer the bottom one)
  • 该视频向您展示了 JavaFx Sdk 下载
  • 如何将其设置为全局库
  • 设置module-info.java(我更喜欢底部的)


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


The entire thing took me only 5mins !!!

整个过程只花了我 5 分钟!!!

回答by jewelsea

Quick summary, you can do either:

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

  1. Include the JavaFX modules via --module-pathand --add-moduleslike in José's answer.

    OR

  2. Once you have JavaFX libraries added to your project (either manually or via maven/gradle import), add the module-info.javafile similar to the one specified in this answer. (Note that this solution makes your app modular, so if you use other libraries, you will also need to add statements to require their modules inside the module-info.javafile).

  1. 在 José 的回答中包含 JavaFX 模块 via--module-path--add-moduleslike。

    或者

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



This answer is a supplement to Jose's answer.

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

The situation is this:

情况是这样的:

  1. You are using a recent Java version, e.g. 13.
  2. You have a JavaFX application as a Maven project.
  3. In your Maven project you have have the JavaFX plugin configured and JavaFX dependencies setup as per Jose's answer.
  4. You go to the source code of your main class which extends Application, you right-click on it and try to run it.
  5. You get an IllegalAccessErrorinvolving an "unnamed module" when trying to launch the app.
  1. 您使用的是最新的 Java 版本,例如 13。
  2. 您有一个 JavaFX 应用程序作为 Maven 项目。
  3. 在您的 Maven 项目中,您已经按照 Jose 的回答配置了 JavaFX 插件和 JavaFX 依赖项。
  4. 您转到扩展 Application 的主类的源代码,右键单击它并尝试运行它。
  5. IllegalAccessError尝试启动应用程序时,您会遇到一个“未命名的模块”。

Excerpt for a stack trace generating an IllegalAccessErrorwhen trying to run a JavaFX app from Intellij Idea:

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(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(LauncherImpl.java:846)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait(PlatformImpl.java:455)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(PlatformImpl.java:428)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
    at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater(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

OK, now you are kind of stuck and have no clue what is going on.

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

What has actually happened is this:

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

  1. Maven has successfully downloaded the JavaFX dependencies for your application, so you don't need to separately download the dependencies or install a JavaFX SDK or module distribution or anything like that.
  2. Idea has successfully imported the modules as dependencies to your project, so everything compiles OK and all of the code completion and everything works fine.
  1. Maven 已成功为您的应用程序下载了 JavaFX 依赖项,因此您无需单独下载依赖项或安装 JavaFX SDK 或模块分发或类似的东西。
  2. Idea 已成功将模块作为依赖项导入到您的项目中,因此一切编译正常,所有代码完成,一切正常。

So it seems everything should be OK. BUT, when you run your application, the code in the JavaFX modules is failing when trying to use reflection to instantiate instances of your application class (when you invoke launch) and your FXML controller classes (when you load FXML). Without some help, this use of reflection can fail in some cases, generating the obscure IllegalAccessError. This is due to a Java module system security feature which does not allow code from other modules to use reflection on your classes unless you explicitly allow it (and the JavaFX application launcher and FXMLLoader both require reflection in their current implementation in order for them to function correctly).

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

This is where some of the other answers to this question, which reference module-info.java, come into the picture.

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

So let's take a crash course in Java modules:

因此,让我们参加 Java 模块速成课程:

The key part is this:

关键部分是这样的:

4.9. Opens

If we need to allow reflection of private types, but we don't want all of our code exposed, we can use the opens directive to expose specific packages.

But remember, this will open the package up to the entire world, so make sure that is what you want:

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

4.9. 打开

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

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

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

So, perhaps you don't want to open your package to the entire world, then you can do:

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

4.10. Opens … To

Okay, so reflection is great sometimes, but we still want as much security as we can get from encapsulation. We can selectively open our packages to a pre-approved list of modules, in this case, using the opens…to directive:

module my.module { opens com.my.package to moduleOne, moduleTwo, etc.; }

4.10. 打开……到

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

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

So, you end up creating a src/main/java/module-info.java class which looks like this:

所以,你最终创建了一个 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;
}

Where, org.jewelsea.demo.javafx.springbootis the name the package which contains the JavaFX Application class and JavaFX Controller classes (replace this with the appropriate package name for your application). This tells the Java runtime that it is OK for classes in the javafx.graphicsand javafx.fxmlto invoke reflection on the classes in your org.jewelsea.demo.javafx.springbootpackage. Once this is done, and the application is compiled and re-run things will work fine and the IllegalAccessErrorgenerated by JavaFX's use of reflection will no longer occur.

其中,org.jewelsea.demo.javafx.springboot是包含 JavaFX 应用程序类和 JavaFX 控制器类的包的名称(将其替换为应用程序的相应包名)。这告诉Java运行时,它是类的OK javafx.graphics,并javafx.fxml就在你的类调用反射org.jewelsea.demo.javafx.springboot包。完成此操作后,应用程序被编译并重新运行,一切都会正常运行IllegalAccessError,JavaFX 使用反射生成的问题将不再发生。

But what if you don't want to create a module-info.java file

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

If instead of using the the Run button in the top toolbar of IDE to run your application class directly, you instead:

如果不是使用 IDE 顶部工具栏中的运行按钮直接运行应用程序类,而是:

  1. Went to the Maven window in the side of the IDE.
  2. Chose the javafx maven plugin target javafx.run.
  3. Right-clicked on that and chose either Run Maven Buildor Debug....
  1. 转到IDE侧面的Maven窗口。
  2. 选择 javafx maven 插件目标javafx.run
  3. 右键单击它并选择Run Maven BuildDebug...

Then the app will run without the module-info.javafile. I guess this is because the maven plugin is smart enough to dynamically include some kind of settings which allows the app to be reflected on by the JavaFX classes even without a module-info.javafile, though I don't know how this is accomplished.

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

To get that setting transferred to the Run button in the top toolbar, right-click on the javafx.runMaven target and choose the option to Create Run/Debug Configurationfor the target. Then you can just choose Run from the top toolbar to execute the Maven target.

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