IntelliJ kann JavaFX 11 mit OpenJDK 11 nicht erkennen

82

Ich habe Probleme, IntellJ dazu zu bringen, JavaFX-Pakete zu erkennen. Bei einem neuen JavaFX-Projekt mit OpenJDK 11 kann IntelliJ beim Versuch, das Projekt zu erstellen, die JavaFX-Pakete nicht erkennen.

Ich habe openjfx:javafx-base-11aus dem Maven Repo importiert .

Ich habe mir andere Fragen angesehen und die Lösungen scheinen von der Überprüfung zu reichen, ob der Bytecode auf der richtigen Ebene ist (meiner ist) und ob die Projektsprache korrekt ist (meiner ist).

Hat jemand irgendwelche Ideen?

Bild 1

Bild 2

Bild 3

Bearbeiten:

Error:

Geben Sie hier die Bildbeschreibung ein

AlwaysNeedingHelp
quelle
Können Sie versuchen, vom Terminal aus zu kompilieren und auszuführen?
Ertrinken
Sie müssen seine Module in Ihremmodule-info.java
Jacob G.
Ich denke, Sie brauchen dieses Artefakt: mvnrepository.com/artifact/org.openjfx/javafx/11 Die Basis enthält nicht alles, was ich denke.
Jorn Vernee
@JornVernee wenn ich versuche, dass ich eine Fehlermeldung bekomme. Ich habe das OP damit bearbeitet.
AlwaysNeedingHelp
1
Wer auch immer Ihnen das gesagt hat, hat sich wahrscheinlich geirrt. Sie benötigen einen erstellen module-info.javaDatei in Ihrem Quellordner und explizit erfordern je nachdem , was JavaFX - Module , die Sie verwenden: requires javafx.controls;, requires javafx.graphics;etc.
Jacob G.

Antworten:

128

Wie in den Kommentaren erwähnt, ist das Starthandbuch der Ausgangspunkt für Java 11 und JavaFX 11.

Der Schlüssel, um wie vor Java 11 zu arbeiten, besteht darin, Folgendes zu verstehen:

  • JavaFX 11 ist nicht mehr Teil des JDK
  • Sie können es in verschiedenen Varianten erhalten, entweder als SDK oder als reguläre Abhängigkeiten (Maven / Gradle).
  • Sie müssen es in den Modulpfad Ihres Projekts aufnehmen, auch wenn Ihr Projekt nicht modular aufgebaut ist.

JavaFX-Projekt

Wenn Sie in IntelliJ ein reguläres JavaFX-Standardprojekt erstellen (ohne Maven oder Gradle), empfehlen wir Ihnen, das SDK hier herunterzuladen . Beachten Sie, dass es auch jmods gibt, aber für ein nicht modulares Projekt wird das SDK bevorzugt.

Dies sind die einfachen Schritte zum Ausführen des Standardprojekts:

  1. Erstellen Sie ein JavaFX-Projekt
  2. Stellen Sie JDK 11 ein (zeigen Sie auf Ihre lokale Java 11-Version)
  3. Fügen Sie das JavaFX 11 SDK als Bibliothek hinzu. Die URL könnte so etwas wie sein /Users/<user>/Downloads/javafx-sdk-11/lib/. Sobald Sie dies tun, werden Sie feststellen, dass die JavaFX-Klassen jetzt im Editor erkannt werden.

JavaFX 11-Projekt

  1. Bevor Sie das Standardprojekt ausführen, müssen Sie diese nur zu den VM-Optionen hinzufügen:

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

  2. Lauf

Maven

Wenn Sie Ihr Projekt mit Maven erstellen, gehen Sie folgendermaßen vor:

  1. Erstellen Sie ein Maven-Projekt mit dem JavaFX-Archetyp
  2. Stellen Sie JDK 11 ein (zeigen Sie auf Ihre lokale Java 11-Version)
  3. Fügen Sie die JavaFX 11-Abhängigkeiten hinzu.

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

Sobald Sie dies tun, werden Sie feststellen, dass die JavaFX-Klassen jetzt im Editor erkannt werden.

JavaFX 11 Maven-Projekt

Sie werden feststellen, dass Maven die erforderlichen Abhängigkeiten für Sie verwaltet: Es werden javafx.base und javafx.graphics für javafx.controls hinzugefügt. Am wichtigsten ist jedoch, dass der erforderliche Klassifizierer basierend auf Ihrer Plattform hinzugefügt wird . In meinem Fall Mac.

Deshalb ist Ihre Gläser org.openjfx:javafx-controls:11sind leer , denn es gibt drei mögliche Klassifizierer (Windows, Linux und Mac - Plattformen), die alle die Klassen und die native Implementierung enthalten.

Wenn Sie dennoch zu Ihrem .m2-Repo gehen und die Abhängigkeiten von dort manuell übernehmen möchten, stellen Sie sicher, dass Sie die richtige auswählen (zum Beispiel .m2/repository/org/openjfx/javafx-controls/11/javafx-controls-11-mac.jar).

  1. Ersetzen Sie die Standard-Maven-Plugins durch die von hier .

  2. Führen Sie mvn compile javafx:run, und es sollte funktionieren.

Ähnliche Arbeiten auch für Gradle-Projekte, wie hier ausführlich erläutert .

BEARBEITEN

Das erwähnte Handbuch Erste Schritte enthält aktualisierte Dokumentation und Beispielprojekte für IntelliJ:

José Pereda
quelle
1
Pfad ist so etwas wie /Users/<user>/Downloads/javafx-sdk-11/lib/, beachten Sie den libOrdner. Das sollte alle Javafx-Gläser enthalten
José Pereda
5
Wenn jemand Probleme mit dem Modulpfad hat, muss er unter Windows ungefähr so ​​aussehen: --module-path = "C: \ Pfad \ zu \ Your \ JavaFX \ lib" --add-modules = javafx.controls, javafx .fxml, javafx.base, javafx.media, javafx.graphics, javafx.swing, javafx.web Beachten Sie das "=" und auch die Anführungszeichen. Dies funktionierte für mich, während jeder andere Ansatz dies nicht tat. Beachten Sie außerdem, dass der Parameter -jar YourJar.jar NACH dem Modulpfad und den Optionen zum Hinzufügen von Modulen stehen muss.
Jalau
4
Hallo @ JoséPereda. Ich habe seit einiger Zeit mit diesem Handbuch zu kämpfen, aber ich kann IntelliJ nicht dazu bringen, meinen Code auszuführen, selbst wenn ich genau das getan habe, was Sie geschrieben haben. Ich erhalte immer noch "Fehler: Java: Modul nicht gefunden: javafx.fxml" und so weiter. Gibt es eine Möglichkeit, einen privaten Chat zu führen, um dieses Problem zu lösen? Vielen Dank.
Davide3i
1
@ Jalau danke! Die Zitate haben es tatsächlich getan, Sie sollten dies als Antwort schreiben.
Derfekt
2
Wenn ich die Distribution für das Beispielprojekt für Gradle erstelle und dann ausführe, wird die Fehlermeldung angezeigt: "Fehler: JavaFX-Laufzeitkomponenten fehlen und müssen ausgeführt werden"
Trejkaz
9

Das Problem, dass JavaFX nicht mehr Teil von JDK 11 ist. Die folgende Lösung funktioniert mit IntelliJ (habe es nicht mit NetBeans versucht):

  1. Fügen Sie die JavaFX Global Library als Abhängigkeit hinzu:

    Einstellungen -> Projektstruktur -> Modul. Gehen Sie im Modul zur Registerkarte Abhängigkeiten und klicken Sie auf das Zeichen "+" hinzufügen -> Bibliothek -> Java-> wählen Sie JavaFX aus der Liste aus und klicken Sie auf Ausgewählte hinzufügen und dann auf Einstellungen anwenden.

  2. Klicken Sie in Ihrem JavaFX-Projekt mit der rechten Maustaste auf die Quelldatei (src) und erstellen Sie eine neue Datei module-info.java . Schreiben Sie in die Datei den folgenden Code:

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

    Diese beiden Schritte lösen alle Ihre Probleme mit JavaFX, das versichere ich Ihnen.

Referenz: Es gibt ein You Tube-Tutorial von The Learn Programming Channel, das alle oben genannten Details in nur 5 Minuten erklärt. Ich empfehle außerdem, es anzusehen, um Ihr Problem zu lösen: https://www.youtube.com/watch?v=WtOgoomDewo

Coder992
quelle
8

Keines der oben genannten hat bei mir funktioniert. Ich habe zu viel Zeit damit verbracht, andere aufgetretene Fehler zu beseitigen. Ich fand das der einfachste und beste Weg.

Dies funktioniert auch für JavaFx auf Jdk 11, 12 und OpenJdk12!

  • Das Video zeigt Ihnen den JavaFx Sdk-Download
  • So legen Sie es als globale Bibliothek fest
  • Setze das Modul-info.java (ich bevorzuge das untere)

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

Das Ganze hat mich nur 5 Minuten gekostet !!!

Yo Apps
quelle
Festlegen, dass eine globale Bibliothek im Jahr 2019.3 verschoben wurde. Können Sie darauf hinweisen, wo sich dies jetzt befindet?
Michael S.
Danke vielmals! Arbeitete auch für mich !!! Upvote!
Daniel Boehm
4

Kurze Zusammenfassung, Sie können entweder:

  1. Fügen Sie die JavaFX-Module über --module-pathund --add-moduleswie in Josés Antwort ein.

    ODER

  2. Wenn Sie Ihrem Projekt JavaFX-Bibliotheken hinzugefügt haben (entweder manuell oder über den Maven / Gradle-Import), fügen Sie die module-info.javaDatei hinzu, die der in dieser Antwort angegebenen ähnelt. (Beachten Sie, dass diese Lösung Ihre App modular macht. Wenn Sie also andere Bibliotheken verwenden, müssen Sie auch Anweisungen hinzufügen, damit deren Module in der module-info.javaDatei enthalten sind.)


Diese Antwort ist eine Ergänzung zu Joses Antwort.

Die Situation ist folgende:

  1. Sie verwenden eine aktuelle Java-Version, z. B. 13.
  2. Sie haben eine JavaFX-Anwendung als Maven-Projekt.
  3. In Ihrem Maven-Projekt haben Sie das JavaFX-Plugin konfiguriert und die JavaFX-Abhängigkeiten gemäß der Antwort von Jose eingerichtet.
  4. Sie gehen zum Quellcode Ihrer Hauptklasse, der Application erweitert, klicken mit der rechten Maustaste darauf und versuchen, ihn auszuführen.
  5. Sie erhalten ein IllegalAccessErrorein „unnamed Modul“ beteiligt , wenn sie versuchen , die App zu starten.

Auszug aus einem Stack-Trace, der IllegalAccessErrorbeim Versuch, eine JavaFX-App über Intellij Idea auszuführen, eine generiert:

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

OK, jetzt steckst du irgendwie fest und hast keine Ahnung, was los ist.

Was tatsächlich passiert ist, ist Folgendes:

  1. Maven hat die JavaFX-Abhängigkeiten für Ihre Anwendung erfolgreich heruntergeladen, sodass Sie die Abhängigkeiten nicht separat herunterladen oder ein JavaFX-SDK oder eine Modulverteilung oder ähnliches installieren müssen.
  2. Idea hat die Module erfolgreich als Abhängigkeiten in Ihr Projekt importiert, sodass alles in Ordnung kompiliert und der gesamte Code vervollständigt wird und alles einwandfrei funktioniert.

Es scheint also, dass alles in Ordnung sein sollte. ABER, wenn Sie Ihre Anwendung ausführen, schlägt der Code in den JavaFX-Modulen fehl, wenn Sie versuchen, mithilfe von Reflection Instanzen Ihrer Anwendungsklasse (beim Aufrufen des Starts) und Ihrer FXML-Controller-Klassen (beim Laden von FXML) zu instanziieren. Ohne Hilfe kann diese Verwendung der Reflexion in einigen Fällen fehlschlagen und die Dunkelheit erzeugenIllegalAccessError . Dies liegt an einer Sicherheitsfunktion des Java-Modulsystems, die es Code von anderen Modulen nicht erlaubt, Reflektion für Ihre Klassen zu verwenden, es sei denn, Sie erlauben dies ausdrücklich (und der JavaFX-Anwendungsstarter und FXMLLoader erfordern beide eine Reflektion in ihrer aktuellen Implementierung, damit sie funktionieren korrekt).

Hier kommen einige der anderen Antworten auf diese Frage module-info.javains Spiel.

Nehmen wir also an einem Crashkurs in Java-Modulen teil:

Der Schlüsselteil ist folgender:

4.9. Öffnet

Wenn wir die Reflektion privater Typen zulassen müssen, aber nicht möchten, dass unser gesamter Code verfügbar gemacht wird, können wir die opens-Direktive verwenden, um bestimmte Pakete verfügbar zu machen.

Aber denken Sie daran, dies wird das Paket für die ganze Welt öffnen. Stellen Sie also sicher, dass Sie genau das möchten:

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

Vielleicht möchten Sie Ihr Paket nicht für die ganze Welt öffnen, dann können Sie Folgendes tun:

4.10. Öffnet… bis

Okay, Reflexion ist manchmal großartig, aber wir wollen immer noch so viel Sicherheit wie möglich durch Kapselung. Wir können unsere Pakete selektiv für eine vorab genehmigte Liste von Modulen öffnen, in diesem Fall mithilfe der Anweisung opens… to:

module my.module {öffnet com.my.package für moduleOne, moduleTwo usw.; }}

Am Ende erstellen Sie also eine src / main / java / module-info.java-Klasse, die folgendermaßen aussieht:

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

Wobei org.jewelsea.demo.javafx.springbootder Name des Pakets ist, das die Klassen JavaFX Application und JavaFX Controller enthält (ersetzen Sie diesen durch den entsprechenden Paketnamen für Ihre Anwendung). Dies teilt der Java-Laufzeit mit, dass es für Klassen in javafx.graphicsund javafx.fxmlin Ordnung ist, die Klassen in Ihrem org.jewelsea.demo.javafx.springbootPaket zu reflektieren . Sobald dies erledigt ist und die Anwendung kompiliert und erneut ausgeführt wurde, funktionieren die Dinge einwandfrei und die IllegalAccessErrordurch JavaFX generierte Verwendung von Reflection tritt nicht mehr auf.

Was aber, wenn Sie keine Datei module-info.java erstellen möchten?

Wenn Sie anstelle der Schaltfläche Ausführen in der oberen Symbolleiste der IDE Ihre Anwendungsklasse direkt ausführen möchten, gehen Sie stattdessen wie folgt vor:

  1. Ging zum Maven-Fenster an der Seite der IDE.
  2. Wählen Sie das Ziel des Javafx Maven Plugins javafx.run.
  3. Klicken Sie mit der rechten Maustaste darauf und wählen Sie entweder Run Maven Buildoder Debug....

Dann wird die App ohne die module-info.javaDatei ausgeführt. Ich denke, das liegt daran, dass das Maven-Plugin intelligent genug ist, um dynamisch einige Einstellungen aufzunehmen, mit denen die App auch ohne module-info.javaDatei von den JavaFX-Klassen reflektiert werden kann, obwohl ich nicht weiß, wie dies erreicht wird.

Um diese Einstellung auf die Schaltfläche Ausführen in der oberen Symbolleiste zu übertragen, klicken Sie mit der rechten Maustaste auf das javafx.runMaven-Ziel und wählen Sie die Option Create Run/Debug Configurationfür das Ziel. Dann können Sie einfach in der oberen Symbolleiste Ausführen auswählen, um das Maven-Ziel auszuführen.

Juwelensee
quelle