JavaFX Application erstellen funktioniert nicht (IntelliJ)?

1 Antwort

Vom Fragesteller als hilfreich ausgezeichnet
Can't build artifacts - fx:deploy is not available in this JDK

Der Task fx:deploy rührt noch vom Java Packager her, der für JDK-Versionen vor 9 benutzt werden konnte, um JavaFX-Applikationen zu bauen. Für spätere JDK-Versionen brauchst du ein 3rd-Party-Tool wie jpackage.

Da ich allerdings annehme, dass du in IntelliJ auch Gradle nutzt, dürfte es auch so gehen:

1) In der build.gradle führst du alle JavaFX-Dependencies auf, die du benötigst.

implementation 'org.openjfx:javafx:<Version>'

implementation 'org.openjfx:javafx-base:<Version>'
implementation 'org.openjfx:javafx-graphics:<Version>'
implementation 'org.openjfx:javafx-controls:<Version>'
implementation 'org.openjfx:javafx-fxml:<Version>'
implementation 'org.openjfx:javafx-media:<Version>'
// ...

Den <Version>-Platzhalter ersetzt du natürlich mit der Versionsnummer, die du verwendest. Welche Dependencies es so für JavaFX gibt, kannst du hier nachschauen. Wenn du einen Eintrag auswählst (und dazu die Version auf der Folgeseite), kannst du dir je Buildtool (Maven/Gradle/Ivy/...) das Snippet für die Buildkonfiguration anschauen (Beispiel).

2) Erstelle eine neue Klasse (die nicht von Application erbt), die folgend als Main Class agiert. Sie beinhaltet also eine main-Methode, in der die main-Methode deiner Application-Klasse aufgerufen wird.

In der build.gradle gibst du sie folglicherweise (für das Manifest) auch als Main Class an:

jar {
  manifest {
    attributes('Main-Class': '<YourMainClass>')
  }
  from {
    configurations.runtimeClasspath.collect {
      it.isDirectory() ? it : zipTree(it)
    }
  }
}
verreisterNutzer  20.11.2021, 23:10

Guten Abend nochmal,

ich habe Deine Tipps angewandt, jedoch komme ich an der Fehlermeldung

Fehler: Zum Ausführen dieser Anwendung benötigte JavaFX-Runtime-Komponenten fehlen

nicht weiter. Diese Fehlermeldung kommt auch nur, wenn ich das Testprogramm exportiert habe und mit der Eingabeaufforderung ausführe.

Da ich immer nur den gleichen Lösungsweg mit "--module-path "C:\Users\..." in Run > Edit Configurations finde, dieser mich aber nicht weiterbringt, weil es ja in der IDE funktioniert, weiß ich mir nach tagelanger Fehlersuche nicht mehr zu helfen.

Vielleicht kannst Du da nochmal ein Auge drauf werfen 😅 Ich habe extra ein neues Projekt erstellt, um Fehler zu vermeiden.

Main | MANIFEST | build.gradle

Ich danke Dir nochmal vielmals für Deine Geduld.

0
regex9  21.11.2021, 08:04
@verreisterNutzer

So wie ich das sehe, hast du das nicht.

Ich schildere einmal eine Schritt-für-Schritt-Anleitung. Dafür nutze ich IntelliJ Community 2021.2.3 mit Gradle sowie Amazon Corretto JDK 16.

1) Gradle Java-Projekt anlegen und Namen festlegen. Ich habe das Projekt buildjavafxtest genannt, so lautet auch die ArticleID. Die GroupID habe ich bei org.example belassen.

2) Unter src/main/java habe ich ein neues Package angelegt: com.example. Dieses beinhaltet dann drei Dateien:

Main.java

package com.example;

public class Main {
    public static void main(String[] args) {
        MainApp.main(args);
    }
}

MainApp.java: Mit deinem Code, die einzigen Änderungen sind der Package-Name, der Klassenname und der Pfad zur FXML.

package com.example;

// ...

public class MainApp extends Application {

    //...
    FXMLLoader
    .load(getClass()
    .getClassLoader()
    .getResource("com.example/Main.fxml"));
    // ...

MainController.java

package com.example;

public class MainController {
}

3) Unter resources/com.example (ein neuer Ordner) liegt die Main.fxml. Ich denke, deren Inhalt kann ich auslassen. Der ist ziemlich irrelevant.

4) IntelliJ wird sich bei diesem Zustand natürlich noch ziemlich aufregen, da es verschiedene Symbole nicht aufösen kann. Nichtsdestotrotz habe ich erst einmal die module-info.java in src/main/java erstellt.

module buildjavafxtest.main {
  requires javafx.controls;
  requires javafx.fxml;
  exports com.example;
}

Zum einen werden die zwei wichtigsten JavaFX-Module angefordert (evt. musst du für dein Projekt noch weitere ergänzen) und zum anderen der Packagepfad für die bisher angelegten Klassen exportiert.

5) Die build.gradle:

plugins {
  id 'application'
  id 'org.openjfx.javafxplugin' version '0.0.10'
  id 'org.beryx.jlink' version '2.12.0'
}
      
group 'org.example'
version '1.0-SNAPSHOT'

repositories {
  mavenCentral()
}

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

jlink {
  options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
  launcher {
    name = 'buildjavafxtest'
  }
}

dependencies {
  testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0'
  testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0'
}

test {
  useJUnitPlatform()
}

jar {
  manifest {
    attributes "Main-Class": "com.example.Main"
  }
  duplicatesStrategy = DuplicatesStrategy.EXCLUDE
  from {
    configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) }
  }
}

Die besteht aus einem zusammenkopierten Mix aus der Anleitung auf OpenJFX (Modular with Gradle), der Standardvorgabe von IntelliJ und dem, was ich schon oben schrieb.

Die Dependencies brauchen (so wie ich es oben schrieb) nicht aufgelistet werden. JLink ist dazu da, dir alle notwendigen Module zu einem Runtime Image zusammenzupacken.

Mein Zusatz

duplicatesStrategy = DuplicatesStrategy.EXCLUDE

hat dabei folgendes Bewandnis: Beim Building werden unterschiedliche module-info-Dateien (z.B. aus JavaFX) entweder in ein Verzeichnis gepackt (INCLUDE) oder nur der erste Fund (EXCLUDE). Der Buildtask kann dies nicht allein entscheiden, deshalb muss eine Strategie vorgegeben werden.

Wichtig ist vor allem der Kniff, den ich schon in meiner Antwort erwähnte: Lege dir eine Stellvertreterklasse mit Einstiegspunkt an und setze diese auch als Startpunkt im Manifest. Wenn du das nicht tust, bekommst du deine Fehlermeldung.

6) Nach Aktualisierung der build.gradle (Ctrl + Shift + O) sollten die Fehler verschwinden, die dir in MainApp zuvor noch um die Ohren geflogen sind. Die Anwendung kann gebaut werden.

7) Im Gradle-Dialog (kann über die Leiste am rechten Fensterrand aufgeklappt werden) gibt es unter Tasks/build den Eintrag jar. Ein Doppelklick darauf und der Build deiner JAR sollte starten und ebenso erfolgreich enden.

8) Die fertige JAR-Datei befindet sich im Projektordner unter build/libs. Du kannst sie über die Konsole starten.

cd "your path to libs folder ..."
java -jar buildjavafxtest-1.0-SNAPSHOT.jar

Bei mir öffnet sich daraufhin, wie erwartet, ein Fenster mit, in meinem Fall, einem Label mit Text.

1
verreisterNutzer  21.11.2021, 11:21
@regex9

Ich danke Dir wirklich sehr und Deine Schritte werde ich in Zukunft versuchen, besser zu verstehen.

Jetzt ist aber das Lustige, dass diese Antwort hier von Dir einen anderen Fehler von mir behoben hat und somit jetzt alles funktioniert. Ich habe mich gerade etwas von IntelliJ und mir veräppelt gefühlt.

0