IntelliJ no puede reconocer JavaFX 11 con OpenJDK 11

82

Tengo problemas para que IntellJ reconozca los paquetes JavaFX. Con un nuevo proyecto JavaFX, con OpenJDK 11, al intentar compilar el proyecto, IntelliJ no puede reconocer los paquetes JavaFX.

Lo he importado openjfx:javafx-base-11del repositorio de Maven.

He analizado otras preguntas y las soluciones parecen ir desde comprobar que el código de bytes está en el nivel correcto (el mío lo está) y que el lenguaje del proyecto es correcto (el mío lo está).

¿Alguien tiene alguna idea?

imagen 1

imagen 2

imagen 3

Editar:

Error:

ingrese la descripción de la imagen aquí

Siempre necesita ayuda
fuente
¿Puedes probar desde la terminal para compilar y ejecutar?
Drowny
Deberá solicitar su (s) módulo (s) en sumodule-info.java
Jacob G.
Creo que necesitas este artefacto: mvnrepository.com/artifact/org.openjfx/javafx/11 la base no contiene todo lo que supongo.
Jorn Vernee
@JornVernee cuando lo intento, aparece un error. Edité el OP con él.
AlwaysNeedingHelp
1
Quien te dijo eso probablemente se equivocó. Es necesario crear un module-info.javaarchivo en la carpeta de origen y explícitamente requerir Cuantas módulos JavaFX que se está utilizando: requires javafx.controls;, requires javafx.graphics;, etc.
Jacob G.

Respuestas:

128

Como se menciona en los comentarios, la Guía de inicio es el lugar para comenzar con Java 11 y JavaFX 11.

La clave para trabajar como lo hacía antes de Java 11 es comprender que:

  • JavaFX 11 ya no es parte del JDK
  • Puede obtenerlo en diferentes sabores, ya sea como un SDK o como dependencias regulares (maven / gradle).
  • Deberá incluirlo en la ruta del módulo de su proyecto, incluso si su proyecto no es modular.

Proyecto JavaFX

Si crea un proyecto predeterminado de JavaFX regular en IntelliJ (sin Maven o Gradle), le sugiero que descargue el SDK desde aquí . Tenga en cuenta que también hay jmods, pero para un proyecto no modular, se prefiere el SDK.

Estos son los sencillos pasos para ejecutar el proyecto predeterminado:

  1. Crea un proyecto JavaFX
  2. Configure JDK 11 (apunte a su versión local de Java 11)
  3. Agregue el SDK de JavaFX 11 como biblioteca. La URL podría ser algo así como /Users/<user>/Downloads/javafx-sdk-11/lib/. Una vez que haga esto, notará que las clases JavaFX ahora se reconocen en el editor.

Proyecto JavaFX 11

  1. Antes de ejecutar el proyecto predeterminado, solo necesita agregarlos a las opciones de VM:

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

  2. correr

Maven

Si usa Maven para construir su proyecto, siga estos pasos:

  1. Cree un proyecto Maven con el arquetipo JavaFX
  2. Configure JDK 11 (apunte a su versión local de Java 11)
  3. Agregue las dependencias de 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>
    

Una vez que haga esto, notará que las clases JavaFX ahora se reconocen en el editor.

Proyecto JavaFX 11 Maven

Notará que Maven administra las dependencias requeridas por usted: agregará javafx.base y javafx.graphics para javafx.controls, pero lo más importante es que agregará el clasificador requerido según su plataforma. En mi caso, Mac.

Es por eso que sus jarras org.openjfx:javafx-controls:11están vacías , porque hay tres clasificadores posibles (plataformas Windows, Linux y Mac), que contienen todas las clases y la implementación nativa.

En caso de que aún desee ir a su repositorio .m2 y tomar las dependencias desde allí manualmente, asegúrese de elegir la correcta (por ejemplo .m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-mac.jar)

  1. Reemplace los complementos predeterminados de Maven con los de aquí .

  2. Ejecutar mvn compile javafx:runy debería funcionar.

Trabajos similares también para los proyectos de Gradle, como se explica en detalle aquí .

EDITAR

La guía de introducción mencionada contiene documentación actualizada y proyectos de muestra para IntelliJ:

José Pereda
fuente
1
La ruta es algo así como /Users/<user>/Downloads/javafx-sdk-11/lib/, observe la libcarpeta. Eso debería contener todos los archivos javafx
José Pereda
5
Si alguien tiene problemas con la ruta del módulo, debe verse así en Windows: --module-path = "C: \ Path \ To \ Your \ JavaFX \ lib" --add-modules = javafx.controls, javafx .fxml, javafx.base, javafx.media, javafx.graphics, javafx.swing, javafx.web Observe el "=" y también las comillas que lo rodean. Esto funcionó para mí, mientras que cualquier otro enfoque no lo hizo. Además, tenga en cuenta que el parámetro -jar YourJar.jar debe venir DESPUÉS de la ruta del módulo y las opciones de agregar módulos.
Jalau
4
Hola @ JoséPereda. He estado luchando con esta guía desde hace un tiempo, pero realmente no puedo hacer que IntelliJ ejecute mi código, incluso si he hecho exactamente lo que ha escrito. Sigo recibiendo "Error: java: módulo no encontrado: javafx.fxml" y así sucesivamente. ¿Alguna posibilidad de tener un chat privado para ayudarme a solucionar este problema? Gracias.
Davide3i
1
@jalau ¡gracias! las citas realmente lo hicieron, debe escribir esto como respuesta.
derfecto
2
Cuando construyo la distribución para el proyecto de muestra para Gradle y luego lo ejecuto, aparece el mensaje de error: "Error: faltan componentes de tiempo de ejecución de JavaFX y son necesarios para ejecutar esta aplicación"
Trejkaz
9

El problema de que JavaFX ya no es parte de JDK 11. La siguiente solución funciona con IntelliJ (no lo he probado con NetBeans):

  1. Agregue la biblioteca global JavaFX como dependencia:

    Configuración -> Estructura del proyecto -> Módulo. En el módulo, vaya a la pestaña Dependencias y haga clic en el signo "+" agregar -> Biblioteca -> Java-> elija JavaFX de la lista y haga clic en Agregar seleccionados, luego Aplicar configuración.

  2. Haga clic con el botón derecho en el archivo de origen (src) en su proyecto JavaFX y cree un nuevo archivo module-info.java . Dentro del archivo escribe el siguiente código:

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

    Estos 2 pasos resolverán todos tus problemas con JavaFX, te lo aseguro.

Referencia: Hay un tutorial de You Tube realizado por el canal The Learn Programming, que explicará todos los detalles anteriores en solo 5 minutos. También recomiendo verlo para resolver su problema: https://www.youtube.com/watch?v=WtOgoomDewo

Coder992
fuente
8

Ninguno de los anteriores funcionó para mí. Pasé demasiado tiempo aclarando otros errores que surgieron. Encontré que esta es la mejor y más fácil forma.

¡Esto funciona para obtener JavaFx en Jdk 11, 12 y en OpenJdk12 también!

  • El video muestra la descarga de JavaFx Sdk
  • Cómo configurarlo como una biblioteca global
  • Configure el módulo - info.java (prefiero el de abajo)

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

¡¡¡Todo me tomó solo 5 minutos !!!

Yo Apps
fuente
Configúrelo como una biblioteca global que se ha movido en 2019.3. ¿Puedes señalar dónde se encuentra ahora?
Michael S.
¡Muchas gracias! ¡¡¡Funcionó también para mí !!! ¡Vota a favor!
Daniel Boehm
4

Resumen rápido, puede hacer lo siguiente:

  1. Incluya los módulos JavaFX a través de --module-pathy me --add-modulesgusta en la respuesta de José.

    O

  2. Una vez que haya agregado las bibliotecas JavaFX a su proyecto (ya sea manualmente o mediante la importación de maven / gradle), agregue el module-info.javaarchivo similar al especificado en esta respuesta. (Tenga en cuenta que esta solución hace que su aplicación sea modular, por lo que si usa otras bibliotecas, también deberá agregar declaraciones para requerir sus módulos dentro del module-info.javaarchivo).


Esta respuesta es un complemento de la respuesta de José.

La situación es esta:

  1. Está utilizando una versión reciente de Java, por ejemplo 13.
  2. Tienes una aplicación JavaFX como proyecto Maven.
  3. En su proyecto Maven, tiene el complemento JavaFX configurado y las dependencias JavaFX configuradas según la respuesta de José.
  4. Vaya al código fuente de su clase principal que extiende Aplicación, haga clic derecho sobre él e intente ejecutarlo.
  5. Se obtiene una IllegalAccessErrorparticipación de un "módulo sin nombre" al intentar iniciar la aplicación.

Extracto de un seguimiento de pila que genera una IllegalAccessErrorcuando se intenta ejecutar una aplicación JavaFX desde Intellij Idea:

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

Bien, ahora estás un poco atascado y no tienes idea de lo que está pasando.

Lo que realmente sucedió es esto:

  1. Maven ha descargado con éxito las dependencias de JavaFX para su aplicación, por lo que no necesita descargar las dependencias por separado ni instalar un SDK de JavaFX o una distribución de módulos ni nada por el estilo.
  2. Idea ha importado con éxito los módulos como dependencias a su proyecto, por lo que todo se compila bien y todo el código se completa y todo funciona bien.

Entonces parece que todo debería estar bien. PERO, cuando ejecuta su aplicación, el código en los módulos JavaFX falla cuando intenta usar la reflexión para crear instancias de su clase de aplicación (cuando invoca el lanzamiento) y sus clases de controlador FXML (cuando carga FXML). Sin alguna ayuda, este uso de la reflexión puede fallar en algunos casos, generando lo oscuro IllegalAccessError. Esto se debe a una característica de seguridad del sistema de módulos de Java que no permite que el código de otros módulos use la reflexión en sus clases a menos que usted lo permita explícitamente (y el lanzador de aplicaciones JavaFX y FXMLLoader requieren una reflexión en su implementación actual para que funcionen correctamente).

Aquí es donde algunas de las otras respuestas a esta pregunta, cuya referencia module-info.java, entran en escena.

Entonces, tomemos un curso intensivo en módulos de Java:

La parte clave es esta:

4.9. Abre

Si necesitamos permitir la reflexión de tipos privados, pero no queremos que todo nuestro código esté expuesto, podemos usar la directiva opens para exponer paquetes específicos.

Pero recuerde, esto abrirá el paquete a todo el mundo, así que asegúrese de que eso sea lo que quiere:

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

Entonces, tal vez no desee abrir su paquete a todo el mundo, entonces puede hacer:

4.10. Abre ... a

De acuerdo, la reflexión es genial a veces, pero aún queremos tanta seguridad como podamos obtener de la encapsulación. Podemos abrir selectivamente nuestros paquetes a una lista de módulos aprobados previamente, en este caso, usando la directiva opens ... to:

module my.module {abre com.my.package a moduleOne, moduleTwo, etc .; }

Entonces, terminas creando una clase src / main / java / module-info.java que se ve así:

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

Donde, org.jewelsea.demo.javafx.springbootes el nombre del paquete que contiene la clase de aplicación JavaFX y las clases de controlador JavaFX (reemplácelo con el nombre de paquete apropiado para su aplicación). Esto le dice al tiempo de ejecución de Java que está bien para las clases en javafx.graphicsy javafx.fxmlpara invocar la reflexión sobre las clases en su org.jewelsea.demo.javafx.springbootpaquete. Una vez hecho esto, y la aplicación se compila y se vuelve a ejecutar, las cosas funcionarán bien y el IllegalAccessErroruso de reflexión generado por JavaFX ya no ocurrirá.

Pero, ¿qué pasa si no desea crear un archivo module-info.java?

Si en lugar de usar el botón Ejecutar en la barra de herramientas superior de IDE para ejecutar su clase de aplicación directamente, usted en su lugar:

  1. Fui a la ventana de Maven en el costado del IDE.
  2. Elija el destino del complemento javafx maven javafx.run.
  3. Hizo clic derecho en eso y eligió Run Maven Buildo Debug....

Entonces la aplicación se ejecutará sin el module-info.javaarchivo. Supongo que esto se debe a que el complemento maven es lo suficientemente inteligente como para incluir dinámicamente algún tipo de configuración que permite que las clases JavaFX reflejen la aplicación incluso sin un module-info.javaarchivo, aunque no sé cómo se logra esto.

Para transferir esa configuración al botón Ejecutar en la barra de herramientas superior, haga clic con el botón derecho en el javafx.runobjetivo de Maven y elija la opción Create Run/Debug Configurationpara el objetivo. Luego, puede elegir Ejecutar en la barra de herramientas superior para ejecutar el objetivo de Maven.

joya
fuente