GUIs mit JavaFX erstellen (1/2)
Java ist eine der beliebtesten Programmiersprachen, die in vielen Bereichen sowohl für Datenverarbeitung, Berechnungen als auch graphische Anwendungen eingesetzt wird. Auf dem TIOBE-Index, der die Beliebtheit und den Anteil von Programmiersprachen weltweit erfasst, liegt Java schon seit einigen Jahren auf Platz 1 – allein aus diesem Grund lohnt es sich, die Sprache zu lernen. Am besten findet sich der Einstieg in eine Programmiersprache mit einem praktischen Beispiel. In diesem Tutorial werden wir daher einen einfachen Taschenrechner mit graphischer Nutzeroberfläche implementieren. Dazu werden wir das Framework JavaFX und die Entwicklungsumgebung Eclipse verwenden. Bevor wir allerdings mit dem Coden beginnen, sollten zuerst die Basics zu Java und JavaFX klar sein.
Java Basics
Bei Java handelt sich um eine stark typisierte, objektorientierte Programmiersprache, die eine ähnliche Syntax wie C oder C++ hat. Die Sprache ist modern und folgt beziehungsweise unterstützt bekannte Programmieransätze und Entwicklungsmuster. Ein großer Vorteil von Java ist, dass die Sprache plattformunabhängig ist – das heißt, man kann Anwendungen sowohl für Linux, Windows und iOS als auch Android entwickeln. Das liegt daran, dass Java-Applikationen nicht nativ auf dem System, auf dem sie gestartet werden, laufen, sondern in einer virtuellen Maschine, der sogenannten Java Virtual Machine (JVM).
Java bietet viele Bibliotheken, die out-of-the-box-Funktionalität für diverse Anwendungszwecke zur Verfügung stellen. Dazu gehören die Nutzung von HTTP-Schnittstellen, die Anbindung an Excel oder PDF, Unit Testing oder das Parsen von Daten. Insgesamt kann im Prinzip jede Idee von Desktop-Applikationen, Apps bis hin zu Plugins mit Java umgesetzt werden. Die einzige Einschränkung hinsichtlich der Anwendungsgebiete sind systemnahe Programme wie Hardwaretreiber.
Historisch gibt es Java seit 1995, 2010 wurde die Sprache von Oracle gekauft. Über die Webseite von Oracle kann man sich sowohl ein Java Runtime Environment (JRE) als auch ein Java Development Kit (JDK) herunterladen. Während man mit einem JRE Java-Applikationen ausführen kann, ist ein JDK notwendig, um in Java auch zu entwickeln. Seit Java 11, der letzten Version mit sogenanntem Long Term Support, kann das JDK für Unternehmen nicht mehr kostenlos genutzt werden und zum Download ist auch für Privatpersonen ein Oracle-Account notwendig.
JavaFX Basics
JavaFX ist ein Framework, mit dem man interaktive graphische Benutzeroberflächen (Graphical User Interfaces) gestalten kann. Bis 2014 wurden GUIs in Java hauptsächlich in AWT oder Swing umgesetzt. Beide Bibliotheken stellen wenig bis keine Funktionalität für die Einbindung und Anzeige von Medien und Animationen bereit, sodass sie den höheren Ansprüchen an Nutzeroberflächen nicht mehr genügten. Man entschied sich, die Entwicklung zu Gunsten eines anderen Frameworks – nämlich JavaFX – einzustellen.
In JavaFX wird für die Verwaltung der einzelnen Oberflächenelemente ein sogenannter Szenengraph (Scene Graph) verwendet. Ein Szenengraphen enthält die logische und meist auch räumliche Anordnung von Szenen. Eine Szene meint in diesem Kontext die dreidimensionale Beschreibung von Objekten unter Einbezug des Blickwinkels des Betrachters. Oberflächen und Szenen können in einer eigenen Sprache auf XML-Basis, der FXML, beschrieben werden. Mit dem Scene Builder, einem eigenständigen Programm, kann die Oberfläche zudem manuell graphisch gestaltet und in FXML umgewandelt werden. Zuletzt können JavaFX-Oberflächen mit CSS gestylt werden.
Auf technischer Ebene erweitert JavaFX die Application-Klasse, hat also einen ähnlichen Lebenszyklus, der aus Initialisierung, Start und Stopp besteht. Die dazugehörigen Methoden start, stop und init können beziehungsweise müssen überschrieben werden. JavaFX stellt außerdem eine launch-Methode als Einstiegspunkt zum Programm bereit. Zum Start des Fensters wird ein Objekt vom Typ Stage übergeben. Dieses Objekt kann konfiguriert werden, beispielsweise durch Methoden wie setTitle, setWidth oder setHeight. Auf dem Stage-Objekt werden Scene-Objekte präsentiert. Ein Scene-Objekt ist eine Baumstruktur, die aus weiteren Komponenten (Knoten beziehungsweise Nodes) besteht. Die Knoten können weitere Kindknoten besitzen, sodass sich eine hierarchische Struktur über alle Oberflächenelemente ergibt.
Setup für das Tutorial
Für den Einstieg in Java und JavaFX werden wir einen kleinen Taschenrechner mit einfacher Nutzeroberfläche schreiben. Zuerst müssen Sie dazu Ihren Computer für die Entwicklung mit Java einrichten, indem Sie ein JDK, JavaFX und eine Entwicklungsumgebung installieren.
Schritt 1: JDK installieren
Sie können ein SDK einfach online, beispielsweise hier oder direkt bei Oracle herunterladen. Die neuste Version Stand 2019 ist Java 13, in diesem Tutorial wird allerdings Java 11, die letzte Version mit Long Term Support, verwendet. Nachdem Sie den Installer heruntergeladen haben, können Sie ihn einfach ausführen. Verifizieren Sie, dass die Installation erfolgreich war, indem Sie auf der Kommandozeile den Befehl
java -version
ausführen.
Falls dieser Befehl fehlschlägt, müssen Sie Java selbst dem Pfad in den Umgebungsvariablen hinzufügen. Tippen Sie dazu Systemumgebungsvariablen bearbeiten in die Suche, öffnen Sie die Systemeigenschaften und anschließend die Umgebungsvariablen.
Prüfen Sie zuerst, dass die JAVA_HOME-Variable auf Ihre Java-Installation zeigt:
Anschließend bearbeiten Sie die Path-Variable und fügen einen Eintrag auf den bin-Ordner Ihrer Java-Installation hinzu:
Starten Sie eine neue Kommandozeile – der obige Befehl sollte nun funktionieren.
Schritt 2: JavaFX installieren
Seit Java 11 ist JavaFX nicht mehr Teil des JDK. Aus diesem Grund müssen wir als nächstes JavaFX separat installieren. Das können Sie beispielsweise hier. Entpacken Sie die Dateien und speichern Sie sie neben dem JDK.
Schritt 3: Eclipse installieren
Abschließend benötigen wir noch eine Entwicklungsumgebung. Die bekanntesten drei Entwicklungsumgebungen für Java sind Eclipse, IntelliJ IDEA und NetBeans. In diesem Tutorial wird Eclipse verwendet. Sie können den Installer von der Eclipse-Webseite direkt herunterladen.
Starten Sie den Installer und wählen Sie Eclipse IDE for Java Developers.
Stellen Sie sicher, dass Eclipse Ihre Java-Installation gefunden hat und wählen einen Ordner zur Installation.
Während der Installation müssen Sie einige Lizenzen und Nutzungsbedingungen akzeptieren, ansonsten gibt es aber keine weiteren Einstellungen, die zu beachten sind. Starten Sie nach der erfolgreichen Installation Eclipse. Zu Beginn müssen Sie einen Arbeitsbereich, den sogenannten Workspace, auswählen, in dem sich Ihr Projekt befinden wird. Legen Sie dazu einen Ordner an.
Anschließend startet sich Eclipse.
Da Eclipse JavaFX nicht von selbst unterstützt, müssen Sie das Framework noch hinzufügen. Klicken Sie dazu in der Navigationszeile auf Help und anschließend auf Install New Software.
Dadurch öffnet sich ein Wizard, in dem Sie Software aus verschiedenen Quellen hinzufügen können. Klicken Sie auf den Button Add… und geben Sie die folgenden Werte für das JavaFX-Repository ein:
Name: e(fx)clipse
Location: http://download.eclipse.org/efxclipse/updates-released/1.2.0/site/
Bestätigen Sie die Eingabe und wählen anschließend alle Ergebnisse aus – insgesamt sollten es zwei sein.
Wenn die Komponenten noch nicht installiert sind, können Sie an dieser Stelle Finish klicken. Die Installation dauert einige Minuten, anschließend müssen Sie Eclipse neustarten. Nun ist JavaFX in Ihrem Eclipse als Projektvorlage verfügbar.
Schritt 4: Das Projekt anlegen
Um ein Projekt anzulegen, klicken Sie auf den Button Workbench in der rechten oberen Ecke. Dadurch gelangen Sie zu allen Projekten, die Ihrem aktuellen Workspace hinzugefügt sind. Aktuell ist noch kein Projekt angelegt. Mit einem Klick auf Create a project gelangen Sie zur Auswahl der verfügbaren Projektvorlagen. Wählen Sie dort die Option JavaFX und dann JavaFX Project. Geben Sie dem Projekt einen Namen, beispielsweise calculatorFX, und klicken Sie Finish. (Anmerkung: Die drei Bilder dazu folgen nun.)
In dem so erstellten Projekt befinden sich folgende Ordnerstruktur:
Es gibt ein Package application, in dem sich zwei Dateien Main.java und application.css befinden. Packages (dt.: Pakete) werden in Java genutzt, um ein Projekt besser zu strukturieren und fungieren damit ähnlich wie Namespaces in C#.
In der Main.java befindet sich zu Beginn folgender Code:
Wie zu sehen ist, wird die launch-Methode von JavaFX in der main-Methode, dem Einstiegspunkt der Applikation, aufgerufen. Zudem wird die Methode start der Application-Klasse überschrieben und erhält als Parameter eine Stage. Innerhalb der start-Methode wird eine Scene erstellt, mit dem CSS aus der application.css-Datei versehen und dann auf der Stage angezeigt. Die application.css-Datei selbst ist zum aktuellen Zeitpunkt leer.
Grundsätzlich ist dieses Programm ausführbar. Bevor Sie das Programm allerdings starten können, müssen Sie die Run Configuration anpassen. Klicken Sie dazu auf den kleinen Pfeil neben dem Start-Button.
Wählen Sie in dem sich öffnenden Fenster den Typ Java Application und geben der Konfiguration einen Namen. Sollten im ersten Reiter Main noch keine Werte eingetragen sein, tragen Sie das Projekt und die Main-Klasse ein:
Project: calculatorFX
Main class: application.Main
Unter dem Reiter Arguments in der Textbox VM Argumente wird außerdem die Zeile
--module-path "<Pfad zu den lib-Dateien von JavaFX>" –add-modules=javafx.controls
benötigt. Durch diese Parameter werden die JavaFX-Dateien der JVM, in der die Applikation läuft, hinzugefügt.
Führen Sie die Konfiguration aus. Sie sollten nun ein leeres Fenster sehen.
Sollte Eclipse den Code an dieser Stelle nicht kompilieren können, weil die JavaFX-Importe nicht aufgelöst werden können, scrollen Sie zum Ende dieses Tutorials. Dort finden Sie eine Anleitung, wie Sie die JavaFX-Klassen manuell verfügbar machen.
Damit ist das Setup von Java, Ihrer IDE und JavaFX beendet und wir können mit der eigentlichen Entwicklung beginnen.
Umsetzung des Taschenrechners
Für die Umsetzung des Taschenrechners werden wir uns an dem sogenannten Model View Controller-Muster, das von FXML unterstützt wird, orientieren. Wie der Name vermuten lässt, gibt es bei diesem Muster drei Komponenten, nämlich das Model, den View und den Controller, die jeweils eine klar definierte Funktion haben. Das Model enthält die Daten, die durch den View dargestellt werden. Der View beinhaltet zwar die Darstellung und nimmt die Nutzereingabe entgegen, definiert aber keinerlei Verarbeitungslogik, denn die Logik wird durch den Controller definiert. Dieser erhält die Nutzereingaben von der Oberfläche, wertet sie aus und manipuliert das Modell und den View entsprechend.
Der Vorteil des MVC-Musters ist es, dass sich einzelne Komponenten später gut austauschen lassen, weil eine klare Trennung der einzelnen Verantwortlichkeiten vorgenommen wird.
Schritt 1: Planung
Bevor wir mit der konkreten Umsetzung anfangen, müssen wir den Umfang des Taschenrechners und das gewünschte Verhalten definieren. Es soll zwei Label geben, eines, das den letzten errechneten Wert anzeigt, und eines für die aktuelle Nutzereingabe. Zudem gibt es sechszehn Knöpfe:
Wenn der Nutzer auf eine der Zahlen oder das Komma klickt, wird die Eingabe entsprechend erweitert. Wählt der Nutzer eine Operation, gibt es zwei Möglichkeiten: Entweder, es gibt bereits ein Zwischenergebnis, oder es gibt keins. Gibt es kein Zwischenergebnis, wird die bisherige Eingabe einfach in das obere Label kopiert, damit der Nutzer die Eingabe des zweiten Operanden vornehmen kann. Gibt es bereits ein Zwischenergebnis, wird die Eingabe je nach gewählter Operation mit dem Zwischenergebnis verrechnet. Klickt der Nutzer auf den =-Button, wird ebenfalls die Berechnung durchgeführt. Gibt der Nutzer nach dem Klick auf den =-Button direkt eine neue Zahl ein, wird das obere Feld geleert, da davon auszugehen ist, dass der Nutzer eine neue Berechnung beginnen möchte.
Schritt 2: Umsetzung der Oberfläche
Im ersten Implementierungsschritt wollen wir nun die Oberfläche, also den View, in FXML gestalten. Klicken Sie dazu mit Rechtsklick auf das application-package, wählen New und dann Other. Dadurch öffnet sich ein Wizard, in dem Sie den Typ FXML Document wählen können.
Nennen Sie die Datei calculator.fxml. Die so automatisch generierte Datei hat folgenden Inhalt:
Zuerst wird definiert, dass es sich um ein xml-Dokument mit Encoding UTF-8 handelt. Außerdem wird die Klasse AnchorPane importiert und als Wurzelelement der Oberflächendefinition festgelegt.
Es ist möglich, diese Datei über einen Rechtsklick mit dem Scene Builder zu bearbeiten. Den Scene Builder können Sie beispielsweise hier herunterladen. Wir werden die Oberfläche allerdings programmatisch zusammenstellen und anschließend mit CSS stylen.
Insgesamt benötigen wir zwei Labels und sechzehn Knöpfe, die wir idealerweise in einem 4×4-Grid anordnen. In der AnchorPane, die bereits vorhanden ist, legen wir also zwei Label, ein GridPane und innerhalb des GridPanes die Buttons an. Dafür müssen wir die einzelnen Klassen importieren:
Anschließend fügen wir die Elemente ein:
Nun setzen wir folgende Attribute:
- fx:id , damit die Komponenten eine ID haben, über die wir sie später beispielsweise im Code referenzieren können. Die GridPane erhält die ID body, die andere Komponenten erhalten eine ID, die der Funktion entspricht (z.B. one und add)
- layoutY , um die Labels und das GridPane untereinander zu präsentieren. Die Labels sollen später eine Größe von 80px haben. Das untere Label benötigt daher das Attribut layoutY=“80“, das GridPane layoutY=“160“
- text , um den Komponenten einen Inhalt zu geben
- GridPane.columnIndex und GridPane.rowIndex auf den Buttons, um sie innerhalb des Grids wie folgt anzuordnen:
Das FXML sollte nach diesen Anpassungen so aussehen:
Damit ist die grobe Definition der Oberfläche abgeschlossen. Um die Oberfläche auch anzuzeigen, müssen wir die start-Methode anpassen. Anstatt die Scene wie in der Vorlage programmatisch zu erstellen, laden wir sie aus der FXML-Datei. Das CSS-Styling fällt vorerst weg, allerdings vergeben wir einen Titel.
Damit Sie das Programm starten können, müssen Sie außerdem die Run Configuration erweitern, da wir nun auch das Modul javafx.xml benötigen.
--module-path "C:\Program Files\Java\javafx-sdk\lib" --add-modules=javafx.controls,javafx.fxml
Das Fenster, das sich nach dem Start öffnet, sollte in etwa so aussehen:
Die Komponenten sind zwar schon sichtbar, der Taschenrechner ist aber noch nicht schön. Das Aussehen der Komponenten kann im FXML durch Attribute wie prefHeight oder prefWidth festgelegt werden. Es ist aber auch möglich, eine CSS-Datei über das Attribut stylesheets einzubinden und das Styling in dieser vorzunehmen. Beachten Sie, dass Sie das Stylesheet nur am Wurzelelement hinzufügen können.
<AnchorPane xmlns:fx="http://javafx.com/fxml/1" fx:id="body" stylesheets="@application.css">
Nachdem Sie das Stylesheet verknüpft haben, können Sie einzelne Regeln festlegen. Diese Regeln gelten für alle Elemente der Oberfläche. Wenn Sie Regeln für eine einzelne Komponente definieren wollen, nutzen Sie das Keyword #id, Regeln für einen Komponententyp benötigen Sie das Keyword .component. Die Definitionen werden wie bei CSS üblich in geschweiften Klammern zusammengefasst. Die Variablen, die Sie konfigurieren können, beginnen mit -fx.
Legen sie zuerst die Schriftgröße 30pt für den gesamten Rechner fest. Wir haben dem AnchorPane die ID body gegeben, daher lautet die entsprechende Regel:
Das Nummernfeld soll die Größe 400 x 400px haben, damit sechszehn Buttons der Größe 100 x 100px Platz finden.
Die Labels wiederum haben beide eine Größe von 80 x 400px. Außerdem legen wir einen schwarzen Rahmen von einer Dicke 0.2px und die Hintergrundfarbe weiß fest.
Zuletzt sollen die Buttons einen ähnlichen Stil wie die Labels besitzen, allerdings mit der Hintergrundfarbe grau und einer Größe von 100 x 100px:
Starten Sie das Programm neu. Nun ist der Taschenrechner deutlich schöner und die Implementierung des Views ist abgeschlossen.
Im
nächsten Teil dieses Tutorials werden wir uns damit beschäftigen, die
Businesslogik des Rechners mithilfe eines Controllers zu implementieren.
Hilfe: JavaFX findet die Importe nicht
Es kann sein, dass Sie zwar ein JavaFX-Projekt erstellen können, aber Eclipse die Importe anschließend nicht auflösen kann, sodass der Code nicht ausführbar ist. In diesem Fall müssen Sie die JavaFX-Jars manuell hinzufügen. Klicken sie dazu mit einem Rechtsklick auf das Projekt und öffnen Sie die Properties.
Gehen Sie in dem sich nun öffnenden Wizard auf Java Build Path und die Karteikarte Libraries. Wählen Sie den Modulepath und klicken Sie auf Add Library…
Wählen Sie User Library und klicken Next.
Zum aktuellen Zeitpunkt sollte es noch keine User Libraries geben. Klicken Sie auf den Button User Libraries…
Sie können nun eine eigene Library hinzufügen. Vergeben Sie dazu einen passenden Namen, beispielsweise JavaFX. Nachdem Sie den Namen bestätigt haben, hat Eclipse eine leere Library erzeugt.
Nun müssen Sie dieser Bibliothek die Jars von JavaFX über den Button Add External JARs… hinzufügen. Diese befinden sich im lib-Ordner der JavaFX-Dateien, die Sie zu Beginn des Setups heruntergeladen haben.
Fügen Sie die Dateien hinzu und speichern die Änderungen. Die Bibliothek befindet sich nun im Modulepath.
Nachdem Sie die Änderungen über den Button Apply and Close angewandt haben, sollte Eclipse die Abhängigkeiten auflösen können.
Sehr gutes Beispiel,
in Eclipse läuft es auch wie beschrieben. Eine runnable jar die ich daraus erzeuge terminiert allerdings mit der Fehlermeldung : Error: JavaFX runtime components are missing, and are required to run this application. Es ist mir bisher generell nicht gelungen eine lauffähige runnable jar zu erzeugen, die JavaFx-Elemente enthält, selbst einfachste Beispiele funktionieren nicht. Ohne FX gibt es diese Probleme nicht.
Haben Sie evtl. Ideen?
Sehr guter Artikel!
Ich bin da noch recht neu in Android Apps programmieren und benutze dabei AS3.6 mit Kotlin (soll ja die Sprache der Zukunft sein auf dem Gebiet).
Ich möchte eine App programmieren, bei der ein Pentagramm (Notenlinien) mit den Noten einer Musik-Tonleiter drauf.
Jetzt soll jede Note abgespielt werden und die jeweilige Note sich dabei verfärben (zur besseren Orientierung).
Ich hoffe, Sie verstehen, wie das aussehen soll.
Meine Frage ist (da es keine Bibliothek gibt, die das bietet) nun, kann ich das am Besten mit JavaFX machen?
Oder brauche ich doch was anderes?
Danke
Hallo Herr Kafkoulas,
danke für Ihren Kommentar. JavaFX ist hierfür sicherlich gut geeignet. Vielleicht gibt es aber auch Frameworks die speziell für Ihre App Vorteile bieten (z.B. https://tornadofx.io/).
Beste Grüße,
Michael Bonacina