JavaFX JavaFX14, die Installation

macaubas

Mitglied
Hallo Java-Forum.

ich habe mich hier entschieden, eine kleine Anleitung von JAVAFX14 zu dokumentieren.
Angefangen habe ich mal mit Swing, wollte dann diese Anwendung nach FX portieren und habe dabei meine Erfahrungen gemacht.

1. Zuerst mal meine Gedanken zu FX:

- Swing-Applikationen sollen vorteilhaft für FX völlig neu konzipiert werden.
- ab JAVA10 muss FX separat installiert werden (war für mich eine rechte Herausforderung).
- ab JAVA10 gibt's keine Runtime-Umgebung mehr, also keine JRE nur noch JDK (ergibt 80 MB JAVA-Installation für Benutzer).
- grosser Lernaufwand, grösser als bei Swing.
- vielfältige Gestaltungsmöglichkeiten für Grafik-Interface der Applikation mit CSS und FXML.
- FX-Dokumentation oft mangelhaft.
- keiner weiss wohin die Reise geht nachdem sich ORACLE bei FX weitgehend verabschiedet hat.

2. Die Installation.

Ich benutze NETBEANS (zur Zeit Vers, 11.3) unter WIN10. JAVA ist JDK14 mit FX14 und jfxtras10 (darüber später).
Beim Umsteigen von JAVA10 auf JAVA14 hatte ich meine grossen Probleme, FX ist nicht mehr in JAVA integrieret.
Deshalb hier mein Vorgehen:
- Download JAVA14: vorteilhaft bei https://jdk.java.net/java-se-ri/14
- Download JAVAFX: https://gluonhq.com/products/javafx/ (JavaFX Windows x86 SDK, 14.0.1)
- Download SceneBuilder: https://gluonhq.com/products/scene-builder/ (als FXML-Editor)
- Download JFXtras: in Maven Central https://repo1.maven.org/maven2/org/jfxtras/
jfxtras-all/10.0-r1/jfxtras-all-10.0-r1.jar, jfxtras-common/10.0-r1/jfxtras-common-10.0-r1.jar,
jfxtras-controls/10.0-r1/jfxtras-controls-10.0-r1.jar, jfxtras-fxml/10.0-r1/jfxtras-fxml-10.0-r1.jar,
jfxtras-window/10.0-r1/jfxtras-window-10.0-r1.jar
- installieren JDK14 : Netbeans > Tools > Java Platform > Add Platform
- installieren JavaFX14 : Netbeans > Tools > Libraries > New Library , Eingabe : JavaFX14
anschliessend alle *.jar aus javafx-sdk-14\lib in Library importieren
- installieren jfxtras : Netbeans > Tools > Libraries > New Library , Eingabe : jfxtras10
anschliessend alle *.jar aus jfxtras in Library importieren
- installieren SceneBuilder ist SceneBuilder-11.0.0.msi, installieren gemäss Dialog

3. Java-Applikation erstellen

- Netbeans > New Project > Java with Ant > Java Application : ProjectName MacaubasFX
- Properties > Libraries : JDK14 in JavaPlatform
- Classpath : JavaFX14 (ist Library)
- Modulepath : alle *.jar aus C:\xxxxxxx\JAVA\javafx-sdk-14\lib importieren
- Modulepath : alle jfrxtras jar-Files zufügen
- Properties > Run : unter VM-Options Text einfügen :
--module-path "C:\xxxxxxx\JAVA\javafx-sdk-14\lib" --add-modules javafx.controls,javafx.fxml
(Achtung auf "--", nicht vergessen)
- Netbeans > New File > JavaFX > JavaFX Main Class, Name: zB. MacaubasMain
- Netbeans > Properties > Run > Main Class > Browse : MacaubasMain auswählen.
Achtung : die Main-Klasse hier MacaubasFX darf nicht gelöscht werden

Das JAR-File wird wie folgt gestartet:

MacaubasFX.CMD

SET JAVA_HOME=C:\xxxx\JAVA\jdk-14
SET PATH_TO_FX=C:\xxxx\JAVA\javafx-sdk-14
%JAVA_HOME%\bin\java.exe --module-path %PATH_TO_FX%\lib --add-modules javafx.controls,javafx.fxml -jar MacaubasFX.jar
***************************************************************************
* nun sollte beim starten das Fenser mit "Hello World!" sichtbar werden
***************************************************************************

4. Erstellen der Applikation mit Menue

Ziel:
- erstellen eines Start-Windows, in welchem mehrere Fenster geöffnet werden können. Entspricht etwa der Swing-Funktion InternalFrame.
Dazu benutzen ichdie Bibliothek von jfxtras
- Verwendung von Menues.
- Verwendung von Event-Handler
- Applikation ohne FXML, jedoch Aufruf mehrerer Fenster mit FXML.
*********************************************************************

ich ersetzen in MacaubasMain public void start wie folgt:

(dies werde ich später nachholen)
 
K

kneitzel

Gast
Erst einmal super, dass Du Deine Erfahrungen und vor allem Deine Lösungswege hier dokumentierst.

Ich möchte nur zwei Dinge kurz erwähnen, denen Du evtl. auch noch nachgehen kannst:

a) "ergibt 80 MB JAVA-Installation für Benutzer" -> Ich denke, hier kommt jlink ins Spiel. Damit kannst Du halt die notwendige Runtime-Umgebung mit genau den Modulen erstellen, die notwendig sind um eben ein minimalen Download bereit zu stellen. Damit sind die 80 MB nicht mehr notwendig für Anwender Deiner Applikation Applikation. (Und mit Java 14 wäre dann noch jpackage interessant...) Aber ich habe keine Ahnung, wie gut genau dies alles zusammen mit JavaFX funktioniert, da ich es selbst noch nicht genutzt habe und ich nicht weiss, was bei jpackage bei non-goals das "JavaFX-specific features" im Detail bedeutet... Im Zusammenhang mit meinem Punkt b) hoffentlich nicht viel :)
Und bezüglicher dieser Thematik ist evtl. auch dieser aktuelle parallele Thread interessant.

b) "ab JAVA10 muss FX separat installiert" Hier möchte ich die Möglichkeit erwähnen, dies über eine gradle oder maven Abhängigkeit einzubinden. Dadurch ist keine explizite Installation mehr notwendig und erspart einem da einige Mühen.

Das nur als kleine Ergänzungen in der Hoffnung, da auch noch weitere Anregungen zu geben für Dich und vielleicht Deine Dokumentation hier!
 
Zuletzt bearbeitet von einem Moderator:

mrBrown

Super-Moderator
Mitarbeiter
Erstmal: das heißt Java, nicht JAVA :p

- ab JAVA10 muss FX separat installiert werden (war für mich eine rechte Herausforderung).
Korrekt ist, dass es seit Java 10 nicht mehr im Orcale-Release enthalten ist :) Bei anderen war es schon immer so (zB das normale OpenJDK) bzw ist immer noch nicht so (zB Liberica JDK oder Zulu).

Und der Vorteil ist dadurch natürlich, dass man es zusammen mit dem Programm ausliefert, anstatt auf die installierte Version zu vertrauen, die Release-Strategie war dabei schon mit Java 8 sehr unglücklich.

- ab JAVA10 gibt's keine Runtime-Umgebung mehr, also keine JRE nur noch JDK (ergibt 80 MB JAVA-Installation für Benutzer).
Ein JRE gibts schon noch, nur nicht mehr von Oracle direkt, aber zb hier: https://adoptopenjdk.net/releases.html
Das hat dann grob etwa 40MB, im Verglich zu den 190MB des JDKs.



Generell würde ich jedem empfehlen, JavaFX NUR in Verbindung mit Maven oder Gradle zu nutzen. Schritte 2, 3 & 4 schrumpfen dadurch zusammen auf quasi nur "JDK + Maven installieren, Projekt aus Archetype erstellen, Starten".
 

dzim

Top Contributor
Ich sag nur eins: https://bell-sw.com/pages/downloads/#/java-14-current

-> Full JDK auswählen und man hat ein Java 14 mit JavaFX gebundelt. Und einen Installer.

Wenn ich auf Windows bin und JavaFX undbedingt im JDK brauche, nehme ich also die Full JDK-Variante von Liberica.
Ansonsten, da ich meist mit Maven oder Gradle schaffe, tut es auch ein beliebiges JDK ohne JavaFX und füge JavaFX als reguläre Dependency hinzu (ist definitiv meine favorisierte Variante, aber wenn man mit jpackage ein Standalone Bundle der App haben möchte, ist Full Liberica JDK einfacher zu verwenden).
 

macaubas

Mitglied
und hier die Fortsetzung:
(nur Menu Artikel hat EventHandler, Dokumente und Help nicht)

ich ersetzen in MacaubasMain public void start wie folgt:


Java:
Java:
package macaubasfx;

import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXMLLoader;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
import jfxtras.scene.control.window.CloseIcon;
import jfxtras.scene.control.window.MinimizeIcon;
import jfxtras.scene.control.window.Window;

public class MacaubasMain extends Application {

    @Override
    public void start(Stage primaryStage) {
        final Group root = new Group();
        Label lab0 = new Label("MacaubasFX");

        final Menu Art = new Menu("ARTIKEL");
        final Menu Doc = new Menu("DOKUMENTE");
        final Menu Help = new Menu("Help");
        MenuBar mb = new MenuBar();
        mb.getMenus().addAll(Art, Doc, Help);

        MenuItem A0 = new MenuItem("öffne Ao.fxml");
        MenuItem A1 = new MenuItem("öffne Au.fxml");
        MenuItem A2 = new MenuItem("öffne beide");
        Art.getItems().addAll(A0, A1, A2);
        //StackPane root = new StackPane();
        root.getChildren().add(mb);

        lab0.setVisible(true);
        lab0.setLayoutX(400);
        lab0.setTranslateY(400);
        lab0.setFont(Font.font("Times new roman", FontWeight.BOLD, 40));
        lab0.setTextFill(Color.web("#ADD8E6"));
        root.getChildren().add(lab0);

        Scene scene = new Scene(root, 700, 700);
        primaryStage.setTitle("MacaubasFX");
        primaryStage.setScene(scene);
        primaryStage.show();

        //Event Handler
        A0.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                System.out.println("---- A0 wurde gewählt -------");
                Window w = new Window();
                try {
                    starteAx(root, w, primaryStage, "Ao.fxml", "Auto");
                } catch (IOException ex) {
                    Logger.getLogger(MacaubasMain.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        A1.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                System.out.println("---- Au wurde gewählt -------");
                Window w = new Window();
                try {
                    starteAx(root, w, primaryStage, "Au.fxml", "Auto");
                } catch (IOException ex) {
                    Logger.getLogger(MacaubasMain.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });
        A2.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent arg0) {
                System.out.println("---- beide wurden gewählt -------");
                Window w = new Window();
                try {
                    starteAx(root, w, primaryStage, "A0_A1.fxml", "Auto");
                } catch (IOException ex) {
                    Logger.getLogger(MacaubasMain.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        });

        try {
            File dir = new File(MacaubasMain.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
            StaCla1.GLOBAL.put("JarDir", dir);
        } catch (URISyntaxException ex) {
            Logger.getLogger(MacaubasMain.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public static void main(String[] args) {
        launch(args);
    }

    Window starteAx(Group gr, Window w, Stage primaryStage, String XML, String Titel) throws IOException {
        StaCla1.Comps.clear();
        w.setLayoutX(20);
        w.setLayoutY(20);
        w.setPrefSize(700, 700);
        w.getLeftIcons().add(new CloseIcon(w));
        w.getRightIcons().add(new MinimizeIcon(w));
        w.setTitle(Titel);
        w.getContentPane().getChildren().add(FXMLLoader.load(getClass().getResource(XML)));
        gr.getChildren().add(w);     
        //Test Event
        w.getLeftIcons().get(0).setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(ActionEvent event) {
                System.out.println("\n***** das Window wird geschlossen *****");
                Node N = w.getContentPane().getChildren().get(0);
                N.setRotate(N.getRotate() + 5);
                int i = 0;
                w.close();
            }
        });
        return w;
    }

}
 

macaubas

Mitglied
ich wolltetesten, wie ich 2 FXML-Files innerhalb eines FXLM-Files aufrufen kann,
deshalb erstelle ich 3 FXML-Files :
- A0_A1.fxml ist das Fenster, welches Ao (SplitPane oben) und Au (SplitPane unten) enthält)

Ao.fxml
Java:
XML:
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" fx:id="A_O" prefHeight="330.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="macaubasfx.AoController">
   <children>
      <CheckBox fx:id="ChBox1" layoutX="405.0" layoutY="93.0" mnemonicParsing="false" text="CheckBox" />
      <Button fx:id="bSuch" layoutX="466.0" layoutY="41.0" mnemonicParsing="false" text="Button" />
      <Label fx:id="TxtFeld1_" layoutX="48.0" layoutY="24.0" text="Label" />
      <TextField fx:id="TxtFeld1" layoutX="48.0" layoutY="41.0" />
      <TextField fx:id="TxtFeld2" layoutX="48.0" layoutY="98.0" />
      <TextArea fx:id="TxtA1" layoutX="349.0" layoutY="159.0" prefHeight="140.0" prefWidth="200.0" />
      <Label fx:id="TxtFeld2_" layoutX="48.0" layoutY="76.0" text="Label" />
      <RadioButton fx:id="RBut1" layoutX="405.0" layoutY="128.0" mnemonicParsing="false" text="RadioButton" />
   </children>
</AnchorPane>

Au.fxml
Java:
XML:
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane fx:id="A_U" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="macaubasfx.AuController">
   <children>
      <TabPane layoutX="30.0" layoutY="40.0" prefHeight="251.0" prefWidth="539.0" tabClosingPolicy="UNAVAILABLE">
        <tabs>
          <Tab text="Untitled Tab 1">
            <content>
              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                     <children>
                        <Label fx:id="label55" layoutX="63.0" layoutY="51.0" text="Label" />
                     </children></AnchorPane>
            </content>
          </Tab>
          <Tab text="Untitled Tab 2">
            <content>
              <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0">
                     <children>
                        <TableView fx:id="Tabl1" layoutX="36.0" layoutY="24.0" prefHeight="139.0" prefWidth="200.0">
                          <columns>
                            <TableColumn prefWidth="75.0" text="C1" />
                            <TableColumn prefWidth="75.0" text="C2" />
                          </columns>
                        </TableView>
                     </children>
                  </AnchorPane>
            </content>
          </Tab>
            <Tab text="Untitled Tab">
              <content>
                <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="180.0" prefWidth="200.0" />
              </content>
            </Tab>
        </tabs>
      </TabPane>
      <Label fx:id="Label66" layoutX="49.0" layoutY="14.0" text="Label" />
   </children>
</AnchorPane>


A0_A1.fxml
Java:
XML:
<?xml version="1.0" encoding="UTF-8"?>

<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>

<AnchorPane id="AnchorPane" prefHeight="700.0" prefWidth="700.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="macaubasfx.A0_A1Controller">
   <children>
      <SplitPane dividerPositions="0.5404040404040404" layoutX="14.0" layoutY="34.0" orientation="VERTICAL" prefHeight="700.0" prefWidth="700.0">
        <items>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="700.0" prefWidth="700.0">
               <children>
                  <fx:include fx:id="tabo" source="Ao.fxml" />
                  <Button fx:id="But0" layoutY="2.0" mnemonicParsing="false"  text="But0" />
               </children>
            </AnchorPane>
          <AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="81.0" prefWidth="350.0">
               <children>
                  <TextField fx:id="Txt0" layoutX="14.0" layoutY="14.0" />
                  <fx:include fx:id="tabu" source="Au.fxml" />
               </children>
            </AnchorPane>
        </items>
      </SplitPane>
   </children>
</AnchorPane>
 
Zuletzt bearbeitet von einem Moderator:

macaubas

Mitglied
ja, habe ich bei den FXLM vergessen:
für A0_A1.fxml, Ao.fxml und Au.fxml muss je ein Controller erstellt werde.
Rechs-Click auf File und Make Controller
------------------------------------------
Aber zu @dzim :
wie setze ich jetzt noch die Code-Blocks für die XML ???, bitte um Antwort
 

Ähnliche Java Themen


Oben