Mit neuem Schwung

Java-Tutorial für Einsteiger – Teil 5: User Interface bauen mit JavaFX

Java-Tutorial für Einsteiger – Teil 5: User Interface bauen mit JavaFX

Mit neuem Schwung

Java-Tutorial für Einsteiger – Teil 5: User Interface bauen mit JavaFX


Im fünften Teil unseres Java-Tutorials führen wir das Thema Oberflächengestaltung fort. Haben wir uns in Teil 4 mit den Grundlagen von Swing beschäftigt, geht es nun um JavaFX. Sie lernen, wie man JavaFX-UIs im Code und mit dem Design-Werkzeug Scene Builder baut. Zum besseren Nachvollziehen übertragen wir unser Code-Beispiel \"Word Cloud\" von Swing nach JavaFX.

Erste Schritte mit JavaFX

Desktop-Anwendungen, die mit Swing gebaut werden, sehen gelegentlich etwas altbacken aus. Deutlich mehr visuellen Glanz verspricht JavaFX. Diese Bibliothek ist seit einigen Versionen Bestandteil des JDK und muss nicht erst extra installiert werden.

Durch einige technische Unzulänglichkeiten ist sie jedoch nicht so richtig aus dem Knick gekommen. Eine eigene Sprache JavaFX Script war wohl der falsche Weg. Oracle hat sich nun seit längeren zu JavaFX bekannt. Um damit ein modernes UI zu bauen, braucht es nunmehr nur noch Java. Wir haben unsere Beispielanwendung nach JavaFX konvertiert. Sehen Sie selbst, wie das funktioniert!

 

Java-Tutorial für Einsteiger: Professionell von Beginn an!

java tutorialDieses Java-Tutorial führt Sie Schritt für Schritt in die Programmierung mit Java ein. Anhand einer durchgängigen GUI-Beispielanwendung werden die wichtigsten Programmierkonzepte, Sprachkonstrukte und Werkzeuge in einem professionellen Setting vorgestellt.

 

Java-Tutorial Teil 5: User Interface bauen mit JavaFX

Moderne Applikationen sollen heute nicht nur funktional fehlerfrei, sondern auch ansprechend im Design sein. Diese Aussage gilt nicht nur für privat genutzte Apps, sondern auch für klassische Business-Anwendungen, die oft in Java erstellt werden. Das User Interface (UI) soll dabei zu einem positiven Benutzererlebnis beitragen. Trotz Plattformunabhängigkeit und seit langem auch guter Performance besteht bei vielen Anwendern genau aus diesem Grund eine grundsätzliche Skepsis gegenüber in Java programmierter Software. Eine typische Aussage ist: „Die Oberfläche wirkt angestaubt“. Irgendwie kann das gesamte Erscheinungsbild nicht mit nativen Anwendungen mithalten.

Moderne Benutzeroberflächen arbeiten mit vielfältigen Features, beispielsweise Flat-Design, Transparenz-Effekten, modern gestalteten Steuerelementen und vielem mehr. Prägend sind die designtechnischen Entwicklungen der mobilen Plattformen. Apps für iOS, Android und Windows 10 haben viel dafür getan, dass Software nicht nur funktioniert, sondern dass es auch Freude macht, die Programme zu bedienen.

Lesen Sie auch: 20 JavaFX-Anwendungen aus der Praxis: So schön kann ein Java UI sein!

Für Windows gibt es mit Windows Presentation Foundation schon seit langem eine entsprechende Technologie, die es erlaubt, auch für den Desktop moderne und ansprechende Oberflächen zu gestalten. Java hatte hier lange Zeit einen deutlichen Nachteil. Nachhelfen konnte man mit Komponenten von Drittherstellern. Insgesamt musste man jedoch einigen Aufwand betreiben. Der Grund ist recht simpel: Die etablierte Swing-Technologie ist über die Zeit einfach in die Jahre gekommen.

JavaFX war bereits 2006 angetreten, um diesen Missstand zu beheben. Technologische Hürden und organisatorische Stolpersteine verhinderten jedoch lange Zeit einen Durchbruch. Heute ist JavaFX Bestandteil des JDK, und man kann es zur Erstellung moderner Oberflächen produktiv anwenden. Um Sie mit JavaFX vertraut zu machen, haben wir in diesem Online-Artikel folgende Informationen für Sie zusammengestellt:

  • Technische Hintergründe zu JavaFX
  • UI mit Scene Builder
  • Beispiel App in JavaFX.

Lassen Sie uns starten!

Technische Hintergründe

Wie integriert sich JavaFX in Java? Die Antwort auf die Frage finden Sie, wenn Sie sich Abbildung 1 intensiv betrachten. Gezeigt wird die Architektur von JavaFX.

Abbildung_1

Abbildung 1: Architektur von JavaFX [1].

Auf unterster Ebene befindet sich erwartungsgemäß die Java Virtual Machine (JVM). Was ist Prism? Es handelt sich um eine relativ neue Rendering Engine für Grafiken. Diese greift – sofern verfügbar – auf die Grafikhardware des Rechners zurück. Unter den Betriebssystemen OS X und Linux wird mit Hilfe von OpenGL gerendert. Unter Windows wird Direct 3D verwendet. Gibt es keine Unterstützung durch die Hardware beim Rendering, so wird auf Java 2D zurückgegriffen. Das Glass Windowing Toolkit stellt Low-Level-Betriebssystemroutinen zur Verfügung. Dazu gehören die Fenster- und Ereignisverwaltung. Die Media Engine bietet Unterstützung für Audio und Video. Die Web Engine ermöglicht das Einbetten von Web-Inhalten. Alle genannten Elemente von JavaFX werden über das Quantum Toolkit miteinander verknüpft. Dem Programmierer wird ein JavaFX API zur Verfügung gestellt. Darüber erfolgt die gesamte Kommunikation. Ein tieferes Wissen über die angesprochenen Elemente von JavaFX ist daher nicht unbedingt notwendig.

Der Lebenszyklus einer JavaFX-Anwendung

Grafische Applikationen laufen meist in Form eines Lebenszyklus ab. Dieses ist bei einer JavaFX-Anwendung nicht anders. Der Lebenszyklus einer JavaFX-Anwendung besteht aus den Methoden:

launch => init => start => stop

JavaFX-Anwendungen leiten von der Klasse Application ab. Die genannten Methoden werden damit vererbt und müssen durch Überschreiben mit eigenem Leben gefüllt werden. Der ursprüngliche Einstiegspunkt für eine Java-Anwendung ist bekanntermaßen die main-Methode. Von dieser wird direkt an die launch-Methode weitergeleitet und damit beginnt der Lebenszyklus. Innerhalb der init-Methode können Aufrufparameter der Applikation ausgelesen werden. Diese Methode kann auch leer bleiben. Die start-Methode ist der Kernpunkt einer JavaFX-Anwendung. Diese muss überschrieben werden. JavaFX übergibt der Methode ein Objekt vom Typ Stage (Bühne). Darunter versteht man eine Art Hauptcontainer. Wie lange läuft eine JavaFX-Anwendung? So lange, bis das letzte Fenster der Applikation geschlossen wurde oder die Methode Platform.exit aufgerufen wird.

Der Methode start wird ein Parameter der Klasse Stage übergeben. Innerhalb eines Stages-Objektes können eine oder mehrere Scene-Objekte präsentiert werden. Die Analogie zu einem Theater ist offensichtlich. Stage ist die Bühne, und auf dieser können eine oder mehrere Szenen spielen. Über Eigenschaften kann das Stage-Objekt konfiguriert werden. Dazu gehören zum Beispiel die Größe (setWidth, setHeight) oder der Titel (setTitle).

Ein Objekt der Klasse Scene ist wiederum hierarchisch aufgebaut. Es handelt sich um einen Baum (Tree), der aus einzelnen Knoten besteht (Nodes). Knoten wiederum können so genannte Parent-Nodes enthalten. Diese sind visuell nicht sichtbar (zum Beispiel BorderPane, HBox, VBox) und nehmen weitere Elemente (Kinder) auf. Kind-Elemente sind die typisch sichtbaren Elemente eines UI, wie Buttons, Textfelder usw. Auf diese Weise können mit JavaFX ganze Szenen erstellt werden. Eine Szene wird innerhalb der Stage-Klasse zur Anzeige gebracht. Auch JavaFX verwendet eine relative Anordnung der Elemente. Wenn Größenänderungen am Fenster erfolgen, erfolgen die Anpassungen in der Szene automatisch.

Hello World

Ein Beispiel sagt bekanntlich mehr als 1.000 Worte! Das ist bei JavaFX nicht anders. Traditionell folgt daher ein einfaches „Hello World“. Legen Sie dazu in NetBeans ein neues Projekt an und wählen Sie im Assistenten im Ordner JavaFX Application (Abbildung 2).

Abbildung_2

Abbildung 2: In NetBeans wird ein neues JavaFX-Projekt angelegt.

Danach passen wir den Quellcode gemäß dem folgenden Listing an:


public class HelloWorld extends Application {
    private Label;
    @Override public void init() {        
             label = new Label("Hello World"); 
     }
    
     @Override public void start(Stage stage) {
            StackPane root = new StackPane();       
            root.getChildren().add(label);
            Scene = new Scene(root, 200, 200);
            stage.setTitle("Hello World Example");        
            stage.setScene(scene);        
            stage.show();    }
    
     @Override public void stop() {
         }
    
       public static void main(String[] parameters) {       
              launch(parameters);   
       } 
}

Sehen wir uns diese paar Zeilen Quellcode in Ruhe an:

  1. Beginnen wir ganz unten. Die main-Methode ruft den neuen Einstiegspunkt für eine JavaFX-Anwendung auf. Dazu wird auf die Methode launch verwiesen.
  2. Innerhalb der Methode init wird lediglich ein neues Objekt der Klasse Label erzeugt, welches später für die Anzeige des Textes „Hello World“ dient.
  3. Die Methode start wird ebenso überschrieben. Hier definieren wir eine Scene, dessen Hauptelement eine StackPanel darstellt. Das Objekt der Klasse Scene wird dem Objekt der Klasse Stage zugewiesen. Die Größe und der Titel werden ebenso definiert. Mittels stage.show wird das Fenster angezeigt. Das war es auch schon!
  4. Die überschriebene Methode stop bleibt leer! Das Programm wird mit dem Schließen des Fensters beendet.

Damit haben Sie das Prinzip einer JavaFX-Applikation verstanden. Anwendungen jenseits von Hello World haben natürlich mehrere Fenster und eine Vielzahl von Steuerelementen. Diese werden alle innerhalb der start-Methode generiert. Dabei kann man gestuft vorgehen und das UI modular aufbauen. Das Prinzip bleibt jedoch gleich.

UI mit Scene Builder

Muss man Java-Applikationen mit der Hand bauen? Nein, das wäre ein Rückschritt. Wichtig ist es jedoch zu wissen, dass die grundsätzliche Möglichkeit dazu besteht, d.h. das gesamte UI kann im Java-Code erzeugt werden. Zur Verfügung steht auch ein recht komfortabler UI-Designer, namens Scene Builder. Dieser kann direkt in die Entwicklungsumgebung, zum Beispiel NetBeans, eingebunden werden. Um mit diesem Tool zu arbeiten, startet man am besten wiederum ein neues Projekt, und dieses Mal wählen Sie JavaFX FXML Application (Abbildung 3).

Abbildung_3

Abbildung 3: JavaFX-Anwendung mit Hilfe eines UI-Builders erstellen.

Der Name des Projektes (FXML) sagt es schon: Grundlage für die Definition des UI ist ein XML-Dokument. Das UI wird hier deklarativ erstellt. Sieht man sich die Projektstruktur an (Abbildung 4), fällt einem sofort die Datei FMXLDocument.FXML auf.

Abbildung_4

Abbildung 4: Projektstruktur einer JavaFX FXML Application.

Diese können wir wie gewohnt in NetBeans öffnen und bekommen den folgenden XML-Quelltext:


<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>

<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8.0.111" fx:controller="javafxapplication3.FXMLDocumentController">
    <children>
        <Button fx:id="button" layoutX="126" layoutY="90" onAction="#handleButtonAction" text="Click Me!" />
        <Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
      <CheckBox layoutX="191.0" layoutY="28.0" mnemonicParsing="false" text="CheckBox" />
    </children>
</AnchorPane>

Der Quelltext ist hierarchisch strukturiert, und man erkennt, dass zwei Steuerelemente (ein Button und ein Label) definiert werden. Statt die Datei in NetBeans zu öffnen, können Sie diese auch im Scene Builder bearbeiten (Abbildung 5).

Abbildung_5

Abbildung 5: Öffnen der Datei FMXLDocument.FXML in Scene Builder.

Das Tool Scene Builder (Abbildung 6) wird gestartet. Hier ist eine umfangreiche Bearbeitung des UI möglich.

Abbildung_6

Abbildung 6: Bearbeiten des UI im Scene Builder.

 

Speichert man die Änderungen und schließt das Tool, werden die Änderungen nach NetBeans übertragen und die o.g. XML-Datei wird aktualisiert. Zur Vollständigkeit zeigen wir die Methode start, in welcher das FMXLDocument.FXML geladen wird.


public class JavaFXApplication3 extends Application {
    
    @Override
    public void start(Stage stage) throws Exception {
        Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
        
        Scene scene = new Scene(root);
        
        stage.setScene(scene);
        stage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }
}

Word Cloud in JavaFX

Sie erinnern sich noch an unser Beispiel aus den vorangegangen Teilen des Tutoriums? Richtig, wir hatten damit begonnen, den Rahmen eines Word-Cloud-Generators zu erstellen. Unser bisheriges Projekt basierte auf Swing. Nun übertragen wir das UI nach JavaFX. Dazu starten wir ein neues JavaFX-Projekt und definieren die Oberfläche neu – diesmal ohne UI-Builder. Wir definieren den Aufbau des UI direkt in Java. Dieser fällt nun etwas umfangreicher als beim Einführungsbeispiel aus.


public class JavaFX_Tutorial extends Application {
    Stage window;
    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) throws Exception {
        window = primaryStage;
        window.setTitle("Word Cloud");
        
        //Vbox - Hauptlayout
        VBox haupt = new VBox();
        haupt.setSpacing(10);
        haupt.setPadding(new Insets(8,8,8,8));
                        
        //HBox top, obere Leiste mit Buttons
        HBox top = new HBox();
        top.setSpacing(10);
        
        //Buttons in top
        Button buttonSave = new Button();
        buttonSave.setPrefSize(100, 20);
        Image speichern = new Image(getClass().getResourceAsStream("save32.png"));
        buttonSave.setGraphic(new ImageView(speichern));
               
        Button buttonShow = new Button("Show");
        buttonShow.setPrefSize(100, 20);
        
        //buttom enhält alle Elemente unter top
        HBox bottom = new HBox();
        bottom.setPadding(new Insets(0,0,0,0));
        bottom.setSpacing(10);     
                      
                       
        //Pane kann als Zeichenfläche genutzt werden
        Pane canvas = new Pane();
        canvas.setStyle("-fx-background-color: white;");
        canvas.setPrefSize(700,550);
        
        //TabPane mit Tabs einfügen               
        TabPane tabPane = new TabPane();
        tabPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
        Tab tab1 = new Tab();
        tab1.setText("Content");
        Tab tab2 = new Tab();
        tab2.setText("Style");
        tabPane.getTabs().addAll(tab1, tab2);
        tabPane.setPrefHeight(600);
        tabPane.setPrefWidth(220);
        
        Pane contentTab1 = new Pane();
        contentTab1.setStyle("-fx-background-color: #eeeeee;");
        tab1.setContent(contentTab1);
        
        Pane contentTab2 = new Pane();
        contentTab2.setStyle("-fx-background-color: #eeeeee;");
        tab2.setContent(contentTab2);
           
        //Buttons und Textfeld unter Tabpane
        Button insertButton = new Button();
        insertButton.setText("Add word");
        insertButton.setPrefWidth(220);
        
        TextField wordText = new TextField();
        
        //Neue Vbox mit Tabs, Textfeld und Button
        //Insert VBOX
        VBox bottomRight = new VBox();
        bottomRight.setPadding(new Insets(0));
        bottomRight.setSpacing(8);
        bottomRight.setPrefHeight(800);
        bottomRight.setAlignment(Pos.CENTER);
        
        
        //Alle Komponenten "zusammenfügen" 
        bottomRight.getChildren().addAll(tabPane, wordText, insertButton);
        bottom.getChildren().addAll(canvas, bottomRight);              
        haupt.getChildren().addAll(top, bottom);
        Scene scene = new Scene(haupt, 950,700);
        top.getChildren().addAll(buttonSave, buttonShow);      
        
        
        AtomicInteger i = new AtomicInteger(); //Muss benutzt werden, da normaler Integer in Lamba-Expression nicht benutzt werden kann
     
        //Buttonlogik
        insertButton.setOnAction((e) ->{
            if(!wordText.getText().isEmpty()){
                Text text = new Text(wordText.getText());
                text.setX(100);
                text.setY(200);
                canvas.getChildren().add(text);

                Text t2 = new Text();
                t2.setText(wordText.getText());
                t2.setX(10);
                t2.setY(25 + 20 * i.getAndIncrement());
                contentTab1.getChildren().add(t2);
            }
        });
        
               window.setScene(scene);
        window.setResizable(false);
        window.show();
    }

Und was kommt dabei heraus, wenn wir den Debugger von NetBeans anwerfen? Probieren wir es aus! Wunderbar, unser Programm erstrahlt im modernen Look einer JavaFX-Anwendung (Abbildung 7). Den Quellcode zum Projekt WordCloud finden hier zum Download.

Abbildung_7

Abbildung 7: Unser Beispielprojekt als JavaFX-Anwendung.

 

Fazit

Mit JavaFX ist man gerüstet, um auch plattformübergreifende Applikationen ansprechend aussehen zu lassen. Die jüngsten Zahlen zur Verwendung zeigen, dass bei neuen Projekten auf diese Technologie gesetzt wird. Man kann das UI komplett im Code bauen. Mit Scene Builder steht aber auch ein UI-Builder zur Verfügung, mit dem das Design auf grafische Art- und Weise erledigt werden kann.

JavaFX braucht kein Schattendasein mehr zu fristen. Die Technologie ist endlich soweit, dass man damit auch „schöne“ Business-Applikationen bauen kann. Aufwändig ist das Migrieren einer Swing-Anwendung nach JavaFX. Der Aufwand und der Erfolg hängen stark davon ab, wie weit die einzelnen Schichten voneinander entkoppelt sind [3]. Für ein neues Projekt sollte man JavaFX auf jeden Fall in Erwägung ziehen.

Mehr zum Thema:

Wie man Swing-Anwendungen mit JavaFX modernisiert

Veikko Krypczyk

Dr. Veikko Krypczyk ist begeisterter Entwickler und Fachautor. Er ist stets auf der Suche nach neuen innovativen Lösungen und liebt die Arbeit in der Entwicklungsumgebung. Er bietet Seminare und Workshops zu unterschiedlichen Themen der Softwareentwicklung.

Dr. Veikko Krypczyk studierte Betriebswirtschaftslehrte und promovierte in der Fachrichtung Wirtschaftsinformatik. Er arbeitet als Softwareentwickler, Fachautor und Berater in Fragen rund um die IT. Seine Arbeitsschwerpunkte sind Desktopapplikationen und die 2-D-Grafikprogrammierung. Vielfältige Informationen können auf http://it-fachartikel.de nachgelesen werden. Ein Gedankenaustausch ist unter info@it-fachartikel.de ausdrücklich erwünscht.


Weitere Artikel zu diesem Thema