JavaFX

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche
JavaFX
Entwickler Oracle
Aktuelle Version 8u111 (wird zusammen mit Java SE versioniert)
Betriebssystem Microsoft Windows, Mac OS X, Linux
Programmiersprache Java
Kategorie Klassenbibliothek
Lizenz GPL mit GPL linking exception
OpenJFX auf java.net

JavaFX ist ein Framework zur Erstellung plattformübergreifender Java-Applikationen. Es ist eine Java-Spezifikation von Oracle und setzt sich zum Ziel, das professionelle Erstellen und Verteilen von interaktiven, multimedialen Inhalten und grafischen Benutzeroberflächen (GUIs) über sämtliche Java-Plattformen hinweg zu erleichtern.

Bis 2014 waren AWT und Swing die Standardlösungen für grafische Anwendungen unter Java. Allerdings waren diese in die Jahre gekommen. So gab es Lücken im Bereich Medien und Animation, was jedoch bei modernen grafischen Oberflächen heutzutage gefragt ist. Anstatt in die Weiterentwicklung von AWT/Swing zu investieren, entschied sich Oracle mit JavaFX für eine komplette Neuentwicklung der GUI-Ebene.

JavaFX setzt insbesondere auf einen Szenengraphen (engl. scene graph), der die einzelnen Bestandteile einer GUI verwaltet. Es ermöglicht mit FXML auch eine deklarative Beschreibung von grafischen Oberflächen auf XML-Basis. Mit dem Scene Builder existiert ein grafisches Tool, das die Erstellung von FXML-Dateien vereinfacht. Darüber hinaus können für die Gestaltung auch Web-Technologien wie CSS eingesetzt werden, indem sie in den FXML-Code eingebettet werden.

Da JavaFX komplett alle APIs für moderne Oberflächen anbietet und auch nicht von AWT/Swing abhängig ist, bildet es einen kompletten Media-Stack. JavaFX greift direkt auf alle 2D-/3D-Fertigkeiten moderner Grafikkarten zurück. So kann mit JavaFX auch all das programmiert werden, was bisher eher mit Flash gemacht wurde.[1]

Die JavaFX-Laufzeitumgebung ist seit der Version Java SE Runtime 7 Update 6 Teil jeder x86 Java SE installation.[2]

Entwicklungsgeschichte[Bearbeiten | Quelltext bearbeiten]

Die Geschichte von JavaFX ist nicht besonders geradlinig. Ursprünglich wollte Sun / Oracle JavaFX als Flash-Ersatz im Internet positionieren, jedoch war die Kombination aus HTML5 und CSS3 und JavaScript zu attraktiv. Heutzutage ist es vor allem eine GUI-Bibliothek für klassische Client-Anwendungen.[3]

Version 1[Bearbeiten | Quelltext bearbeiten]

JavaFX wurde im Mai 2007 angekündigt und im Mai des folgenden Jahres auf der Entwicklerkonferenz JavaOne vorgestellt. Am 4. Dezember 2008 gab Sun JavaFX 1.0 offiziell als Entwicklerkit für Windows und Mac OS X frei.[4] Das Release JavaFX 1.0 erschien zusammen mit der Programmiersprache JavaFX Script. Diese Sprache machte es einfach möglich, hierarchische Objektgraphen aufzubauen und bot eine gute Syntax für Object-Binding, womit Zustände synchronisiert werden konnten.[3]

Die Version 1.2 wurde im Juni 2009 veröffentlicht. Sie enthielt unter anderem anpassbare UI-Controls, zusätzliche Layout-Klassen (Tile, Stack, Flow, ClipView, Panel), Unterstützung für RSS/Atom-Feeds. Sie ist nicht abwärtskompatibel. Erst seit dieser Version wurden Linux und Solaris unterstützt. Die Version 1.3 (Codename SoMa) wurde am 22. April 2010 veröffentlicht. Die offensichtlichste Neuerung ist eine teils enorme Steigerung der Performance. Neu ist zudem JavaFX TV, eine offizielle CSS-API zur Gestaltung von JavaFX-Controls, einige neue, gewünschte Controls sowie eine Unterstützung von 3D.[5] Die Version 1.3.1 wurde am 21. August 2010 veröffentlicht und verbesserte die Fortschrittsanzeige beim Aufstarten und das Debugging in Netbeans 6.9.1.

Version 2[Bearbeiten | Quelltext bearbeiten]

JavaFX 2.0 erschien wie angekündigt im dritten Quartal 2011.[6] In dieser Version wird auf JavaFX Script verzichtet, „denn Oracle wollte keine weitere Programmiersprache aufbauen, sondern eine pure Java-API, die Entwickler dann von unterschiedllichen existierenden Skriptsprachen ansprechen konnten.“[3] Deshalb wurden die bestehenden JavaFX Script APIs auf Java portiert. In JavaFX 2.0 wurde außerdem das Hardware-Rendering optimiert, sodass nun Spiele und aufwendige 3D-Darstellungen möglich sein sollen. HTML- und JavaScript-Inhalte rendert JavaFX 2.0 mit Hilfe der WebKit-Bibliothek. Oracle hat im Zuge der Veröffentlichung der neuen Version angekündigt, JavaFX zukünftig als Open-Source-Projekt im Rahmen des OpenJDK weiterzuentwickeln.[7]

JavaFX entwickelte sich nun immer mehr zur Alternative von Swing/AWT. Im August 2012 erschien JavaFX 2.2. Dieses wurde in das JRE/JDK 7 Update 6 integriert. Der Schritt war ungewöhnlich, denn so große Ergänzungen waren bisher als Update im JRE/JDK noch nie gemacht worden.[8]

Die Entwicklung in Richtung Open Source mündete in OpenJFX, wodurch sich zusammen mit dem OpenJDK ein komplett freies Java-System mit GUI-Stack unter der GPL bauen lässt.[8]

Version 8[Bearbeiten | Quelltext bearbeiten]

Mit dem Einzug in den Java-8-Release machte dann auch JavaFX den Releasesprung von 2 auf nun 8. JavaFX 8 bringt einige Neuerungen mit. So bietet es beispielsweise Lambdas als neues Sprachkonstrukt an. Lambda-Ausdrücke helfen, die oft schlecht lesbaren und langen Deklarationen innerer, anonymer Klassen zu vermeiden. So sind beispielsweise Eventhandler als functional interfaces aufgebaut. Eine der großen Neuerungen ist auch das JavaFX-UI-Toolkit, das mit Java 8 als empfohlenes UI-Toolkit ausgeliefert wird. Das Toolkit bietet mit FXML u.a. eine XML-basierte Sprache zum Erstellen von Benutzerschnittstellen an.[9]

Mit der Version 8u33 wurde der ARM-Support von Oracle für JavaFX eingestellt. Daher ist JavaFX nicht mehr in den offiziellen Java Distributionen für ARM enthalten.[10]

Architektur[Bearbeiten | Quelltext bearbeiten]

Die Architektur von JavaFX ist von Grund auf neu und beruht insbesondere nicht auf Swing beziehungsweise AWT. Das bedeutet allerdings auch, dass man JavaFX und AWT/Swing nicht ohne weiteres mischen kann (auch wenn es dafür Lösungen gibt). JavaFX bietet ein komplettes API (Application Programming Interface - Schnittstelle zur Anwendungsprogrammierung) für moderne Oberflächen an. Die wichtigsten Pakete dieser API sind[11]:

Package Beschreibung
javafx.animation Klassen für Animationen auf Basis von Übergängen
javafx.application Die Klassen für den grundsätzlichen Lebenszyklus einer Applikation
javafx.collections Essentielle JavaFX-Collections samt Utilities
javafx.event Das Basis-Framework für JavaFX-Events und deren Behandlung
javafx.fxml Klassen zum Laden einer Objekthierarchie aus einer Markup-Struktur wie FXML
javafx.geometry Klassen für geometrische Operationen auf zweidimensionalen Objekten
javafx.scene Die Basisklassen für das JavaFX Scene Graph API und das Elternpaket der einzelnen Komponenten und Elemente. Es enthält Unterpakete wie canvas, chart, control, effect, image, input, layout, media, paint, shape, text, transform, web, usw.
javafx.stage Top-Level-Container-Klassen für JavaFX-Inhalte
javafx.util Verschiedene Utilities und Hilfsklassen

Die folgende Grafik zeigt die Architektur von JavaFX, wie sie von Oracle offiziell dargestellt wird[12]:

Javafx-architecture.jpg

Wie bei jeder Java-Applikation befindet sich auch bei JavaFX auf der untersten Ebene die Java Virtual Machine (JVM), die für die Ausführung des Java-Bytecodes verantwortlich ist. Hierbei wird im Normalfall jedes gestartete Java-Programm in seiner eigenen virtuellen Maschine (VM) ausgeführt.

Die entsprechenden Entwicklungstools für Java respektive JavaFX werden im Java SE Development Kit (oder nur Java Development Kit, kurz JDK) bereitgestellt. Darauf aufbauend existieren zahlreiche Erweiterungen, die man teils schon sehr lange bei Java nutzen kann, wie beispielsweise Java 2D zum Zeichnen von zweidimensionalen Formen.

Bei Prism[13] handelt es sich um die neue Rendering Engine, die Gebrauch von der Grafikhardware macht (falls unterstützt). Unter anderem werden damit auch Eigenschaften von Java 2D und diverse grafische Effekte wie Schatten, Spiegelungen, Transformationen oder Animationen auf einer hohen Ebene verfügbar gemacht.[14] Dabei wird unter Linux und OS X mit OpenGL gerenderet, während unter Windows Direct3D zum Einsatz kommt. Wird die Grafikhardware nicht unterstützt, wird ein Software-Fallback auf Java 2D verwendet.[15]

Das Glass Windowing Toolkit stellt Low-Level-Betriebssystemroutinen zur Verfügung, wie Fensterverwaltung, Timer oder Ereignisverwaltung. Es dient als plattformabhängige Schicht, die die JavaFX-Plattform mit dem Betriebssystem verbindet.[14]

Die Media Engine basiert auf GStreamer und bietet umfangreiche Unterstützung für Audio und Video an. Die Web Engine ermöglicht die Einbettung von Web-Inhalten in JavaFX-Applikationen. Dazu gehört das HTML-Rendering auf Basis der WebKit-Engine, das hardwareabhängige Rendern über Prism und die Möglichkeit des DOM-Zugriffs und der Manipulation des DOM.[14]

Das Quantum Toolkit verknüpft Prism, Glass Windowing Toolkit, Media Engine und Web Engine und macht diese einheitlich den JavaFX-APIs zugänglich. Das JavaFX-API und das Quantum Toolkit kapseln die Details der tieferliegenden Ebenen und verbergen diese vor dem Anwender. Ein JavaFX-Entwickler braucht also im Prinzip gar nicht zu wissen, wie die tieferliegenden Ebenen funktionieren.[16]

Aufbau einer JavaFX-Anwendung[Bearbeiten | Quelltext bearbeiten]

JavaFX-Lebenszyklus[Bearbeiten | Quelltext bearbeiten]

Lebenszyklus einer JavaFX-Anwendung

JavaFX-Anwendungen erweitern die Basisklasse Application, die Lebenszyklus-Methoden wie init(), start() oder stop() vererbt. Diese Methoden können (oder müssen) in der JavaFX-Anwendung überschrieben werden. Der JavaFX-Launcher kümmert sich darum, dass diese entsprechend aufgerufen werden. JavaFX-Anwendungen benötigen also keine main-Methode: Die eigene statische main(String[])-Methode leitet an die statische launch(String[])-Methode der Application-Klasse weiter und übergibt ihr alle Aufrufparameter.[17] Da die Klassenmethode launch(...) weiss, in welcher Klasse sie aufgerufen wurde, erzeugt sie ein Exemplar dieser Klasse und ruft dann die Lebenszyklusmethoden auf.[18]

Der Lebenszyklus einer JavaFX-Anwendung sieht folgendermaßen aus[19]:

  1. Beim Start der Anwendung konstruiert die JavaFX-Runtime zunächst eine Instanz der Application-Klasse.
  2. Nun wird die init()-Methode der erzeugten Instanz ausgeführt. Diese Methode wird als default leer implementiert und muss nicht zwingend überschrieben werden. Es können hier beispielsweise die Aufrufparameter ausgelesen werden. Es dürfen hier jedoch noch keine UI-Elemente erzeugt werden.[20]
  3. Als nächstes wird die Methode start(javafx.stage.Stage) aufgerufen, die von jeder JavaFX-Anwendung überschrieben werden muss. JavaFX übergibt der Methode eine Stage (deutsch „Bühne“), was etwa der Aufgabe eines Haupt-Containers entspricht und am ehesten mit dem Startfenster verglichen werden kann.
  4. Die JavaFX-Runtime wartet nun, bis die Anwendung beendet wird. Dies ist folgendermaßen möglich:
    • durch Aufruf der Methode Platform.exit()
    • indem das letzte Fenster geschlossen wird und das Attribut implicitExit auf Platform auf true gesetzt ist.
  5. Nun ruft die Runtime die stop()-Methode auf, bevor der Java-Prozess gestoppt wird. Diese Methode muss wiederum nicht zwingend überschrieben werden.

Die Stage (Bühne)[Bearbeiten | Quelltext bearbeiten]

Die Stage bildet den Rahmen für den eigentlichen Inhalt. Die Klasse Scene verwaltet den Szenengraph. Dieser ist ein gewurzelter Baum, der aus Nodes besteht. Parent-Nodes enthalten weitere Nodes, die Blätter-Nodes stellen dagegen die sichtbaren Elemente der GUI dar (Button, Textfeld, Slider, usw.).

Der start(...)-Methode wird eine Stage übergeben. Der Parameter der start(...) ist also vom Typ javafx.stage.Stage. Diese Klasse ist der Top-Level-JavaFX-Container, der immer von der Plattform konstruiert wird - als Parameter der start(...)-Methode. Dies kann am ehesten mit dem Startfenster verglichen werden. Zusätzlich können in einer Applikation weitere Stage-Objekt erstellt werden.[21]

Die Stage kann verwendet werden, um eine oder mehrere Szenen (engl. scenes) zu präsentieren. Die Namensgebung der Basisklassen Stage und Scene ist ans Theater angelehnt: Die Stage ist die Bühne, auf der eine Szene aufgeführt wird. Sie bildet den Rahmen für den eigentlichen Inhalt.[22]

Für ein Stage-Objekt gibt es wie bei einem Fenster über entsprechende Methoden eine Vielzahl von Einstellungsmöglichkeiten, beispielsweise

  • legen setWidth(double value) und setHeight(double value) die Höhe und Breite der Stage fest, und
  • setTitle(java.lang.String value) setzt den Titel des Fensters.

Der StageStyle legt das Erscheinungsbild des Fensters fest. Der Defaultwert ist DECORATED, der ein Fenster mit vom Betriebssystem abhängiger Umrandung und Bedienelementen und weißem Hintergrund anzeigt.[23] Die meisten Eigenschaften eines Stage-Objekts können jedoch nur gelesen werden, denn sie werden von der zugrunde liegenden Plattform geändert.[21]

Die Scene (Szene)[Bearbeiten | Quelltext bearbeiten]

Auf der Stage (Bühne) werden in der Regel eine oder mehrere Szenen präsentiert, die vom Typ javafx.scene.Scene sind. Diese Klasse ist der Container für sämtlichen Inhalt in einem Szenengraphen, der die einzelnen Bestandteile einer GUI verwaltet.

Aus graphentheoretischer Sicht ist der Szenengraph ein gewurzelter Baum, der aus Nodes (deutsch Knoten) besteht. Als innere Knoten gibt es Parent-Nodes, die weitere Nodes (Knoten) als Kinder enthalten können. Ein Blatt (engl. leaf node) hat dagegen keine weiteren Kinder. Die Blätter stellen nun die sichtbaren Elemente der GUI dar (z.B. Buttons, Textfenster und Slider), die Parent-Nodes die unsichtbaren strukturellen Elemente (z.B. BorderPane, HBox und VBox). Eine Applikation muss den Wurzelknoten (Root Node) für den Szenengraphen angeben. Das ist so etwas wie der Ursprung, aus dem sich die gesamte Szene entwickelt. Dafür gibt es ein Argument für den Konstruktor eines Scene-Objekts. Die Scene-Objekte müssen im JavaFX-Application-Thread erstellt und modifiziert werden.[24]

Die Scene ist auch das Bindeglied zwischen dem Fenster, das vom Betriebssystem zur Verfügung gestellt wird und dem Szenengraphen. Wird beispielsweise das Fenster vergrößert, versucht die Scene diese Änderung an den Wurzelknoten weiterzugeben: Sie ruft dazu die Methode isResizable auf dem Root-Node auf, um herauszufinden, ob der Node auf Größenänderungen reagieren möchte. Gibt der Node true zurück, wird die Scene ihn auf die neue Größe verändern, bei false belässt sie ihn.[25][26]

Mit dem Befehl stage.setScene(scene) kommt der Szenengraph über die Klasse Scene auf die Bühne. Zu jedem Zeitpunkt sind alle grafischen Objekte einer JavaFX-Anwendung präsent, d.h. sie existieren nicht nur zum Zeitpunkt des Zeichnens.[27]

Nodes (Knoten)[Bearbeiten | Quelltext bearbeiten]

Hierarchie der Node-Klassen in JavaFX.

Alle Objekte im Szenengraph sind vom Typ Node. Diese bilden also den Inhalt des Szenengraphen. Jeder Knoten und jedes Element im Szenengraphen ist wiederum ein Untertyp der abstrakten Klasse Node.

Eine Unterklasse von Node ist Parent. Die Parent-Nodes sind die Basisklasse für alle Nodes, die weitere Nodes als Kinder enthalten, also Container sind. Von Parent gibt es wiederum Unterklassen:

  • Die Klasse Group fasst mehrere Elemente in einem Knoten zusammen. Sie ermöglicht es beispielsweise, dass Transformationen und Effekte auf die Gruppe angewendet werden und von dieser auf alle Elemente (Kinder) der Gruppe delegiert werden. Der Group-Node führt eine ObservableList von Kindern. Über die Methode getChildren() kann die Liste der Kinder abgerufen werden, der dann über getChildren().add(element) weitere Elemente hinzugefügt werden kann. Eine Group kümmert sich nicht um die Positionen der Kinder und kann nicht über CSS angepasst werden.[28]
  • Die Klasse Region bildet die Basisklasse für alle Controls und Layouts und erweitert die Basisklasse um viele Möglichkeiten für das Styling über CSS. Von Region gibt es eine Unterklasse Pane, die die Kinder über öffentliche Methoden nach außen gibt. Die davon abgeleitete Klasse BorderPane positioniert beispielsweise die Kinder oben (top), links (left), rechts (right), unten (bottom) und in der Mitte (center).
  • Die Klasse Control erweitert die Klasse Region. Sie ist die Basisklasse für Komponenten, die in irgendeiner Form Benutzereingaben erlauben. Dazu gehören beispielsweise Schaltflächen oder Beschriftungen. Jede Control-Komponente lässt sich über CSS wiederum optisch bearbeiten.[29]

JavaFX kommt wie Swing mit einem Satz von Standardkomponenten im Paket javafx.scene.control und hat Control als Basisklasse.[30] Die folgende Übersicht listet die wichtigsten Controls, die in JavaFX zur Verfügung stehen[31]:

Control Verwendung
Label Das Label ist eines der einfachsten Controls. Es besteht aus einem Text und einem weiteren beliebigen Node zur Deklaration. Häufig wird hierfür ein Image verwendet.
Hyperlink Entspricht einem HTML-Hyperlink und wird standardmäßig als blauer unterstrichener Text dargestellt.
Button Ein Button kann gedrückt werden. Der Selektionszustand bleibt erhalten.
RadioButton Ein Auswahlknopf für die Einzelauswahl aus einer Gruppe von Radiobuttons. Der Selektionszustand bleibt erhalten, bis ein anderer Button derselben Gruppe ausgewählt wird.
ToggleButton Ein Auswahlknopf, der in zwei Zuständen existiert: ausgewählt (selected) und nicht ausgewählt. Verhält sich ähnlich wie eine CheckBox oder ein RadioButton.
CheckBox Ein Checkbox ist ein Auswahlkasten mit drei möglichen Zuständen: undefined, checked und unchecked. Der Selektionszustand bleibt bis zur Änderung erhalten.
ChoiceBox Eine Auswahlliste für die Auswahl eines einzelnen Items aus einer vorzugsweise kurzen Liste.
TextField Einzeiliges Freitexteingabefeld mit Cursorsteuerung und Selektion.
TextArea Mehrzeiliges Freitexteingabefeld mit Cursorsteuerung und Selektion.
ListView Standardkomponente zur Anzeige von Listen von Objekten.
TableView Eine Tabellenkomponente, die aus einer Reihe von Spalten (TableColumns) zusammensetzt. Einzelne Zellen werden als TableCell repräsentiert.
TitledPane Ein auf- und zuklappbarer Teildialog.
ScrollPane Dient zum Verschieben und Darstellen eines Ausschnittes mit horizontalem und vertikalem ScrollBar (Rollbalken).

Zunächst sind Controls einfach nur Nodes, die dem SceneGraph hinzugefügt werden können und die dann dargestellt werden. Natürlich stellen die entsprechenden Klassen für UI-Controls diverse spezifische Eigenschaften und Methoden zur Verfügung, um typische Interaktionen mit Anwendern zu unterstützten.

Programmbeispiele[Bearbeiten | Quelltext bearbeiten]

Hello JavaFX World![Bearbeiten | Quelltext bearbeiten]

Das folgende Programmbeispiel zeigt eine typisches Hallo-Welt-Programm in JavaFX:

package application;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class Main extends Application
{
	@Override
	public void start(Stage primaryStage)
	{
		Label label = new Label("Hello JavaFX World!");

		StackPane root = new StackPane();
		root.getChildren().add(label);

		Scene scene = new Scene(root, 400, 300);

		primaryStage.setTitle("Hello JavaFX World!");
		primaryStage.setScene(scene);
		primaryStage.show();
	}

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

Die Klasse Main ist von der Klasse Application abgeleitet. Die eigene main(...)-Methode leitet an die launch(...)-Methode der Application-Klasse weiter. In der erzeugten Instanz der Application-Klasse wird zunächst die init()-Methode ausgeführt, die hier als default leer implementiert bleibt.

Als nächstes wird die start(...)-Methode ausgeführt, die wie hier von jeder JavaFX-Anwendung überschrieben werden muss. JavaFX übergibt der Methode eine Stage, die mit dem Startfenster verglichen werden kann. Innerhalb der start()-Methode werden nun die folgenden Schritte ausgeführt:

  • Es wird ein einfaches Label-Control label kreiert. Der darzustellende Text „Hello JavaFX World!“ wird hier direkt dem Konstruktor übergeben.
  • Nun wird ein StackPane namens root erzeugt. Dieses platziert alle Kindelemente in der Reihenfolge ihres Hinzufügens übereinander. Standardmäßig werden die Komponenten in der StackPane zentriert. Über root.getChildren().add(label) wird nun das zuvor erzeugte Label label hinzugefügt.
  • Nun wird eine Scene scene erstellt, die sich anschließend auf die Stage laden lässt. Die Anwendung muss einen Root-Node (Wurzel-Knoten) für den Szenengraph spezifizieren. In diesem Beispiel ist dies das root-Objekt vom Typ StackPane. Außerdem wird hier dem Konstruktor noch eine spezifische Darstellungsgröße () mitgegeben.
  • Im nächsten Schritt wird über primaryStage.setTitle("Hello JavaFX World!") der Titel des Anwendungsfensters ebenfalls auf „Hello JavaFX World!“ gesetzt. Am wichtigsten ist aber die Zuweisung der Szene scene, die auf den eigentlichen Inhalt verweist. Die show()-Methode versucht nun das Fenster anzuzeigen, indem die Sichtbarkeit auf true gesetzt wird.

Cycle of Life[Bearbeiten | Quelltext bearbeiten]

package application;

import javafx.application.Application;
import javafx.application.Platform;
import javafx.stage.Stage;

public class CycleOfLife extends Application
{
	@Override
	public void init()
	{
		System.out.printf("Die Methode init(), aufgerufen im Thread %s%n",
				Thread.currentThread());
	}

	@Override
	public void start(Stage primaryStage)
	{
	      System.out.printf("Die Methode start(), aufgerufen im Thread %s%n",
                  Thread.currentThread());
	      Platform.exit();
	}

	@Override
	public void stop()
	{
		System.out.printf("Die Methode stop(), aufgerufen im Thread %s%n",
				Thread.currentThread());
	}

	public static void main(String[] args)
	{
		System.out.printf("Die Methode main(), aufgerufen im Thread %s%n",
				Thread.currentThread());
		launch(args);
	}
}

Das Programm liefert in etwa den folgenden Output:

Die Methode main(), aufgerufen im Thread Thread[main,5,main]
Die Methode init(), aufgerufen im Thread Thread[JavaFX-Launcher,5,main]
Die Methode start(), aufgerufen im Thread Thread[JavaFX Application Thread,5,main]
Die Methode stop(), aufgerufen im Thread Thread[JavaFX Application Thread,5,main]

Die main(...)-Methode von CycleOfLife ruft Application.launch(...) auf und eine Instanz der Application-Unterklasse wird im JavaFX Application Thread erzeugt. Die init()-Methode wird im JavaFX Launcher Thread aufgerufen, bei welchem es sich um den Thread handelt, der die Applikation startet. Um die start()- und stop()-Methoden auszuführen, erzeugt JavaFX einen Thread namens JavaFX Application Thread. Die Erzeugung von Stage- und Scene-Objekten und Modifikationen am Szenengraphen müssen innerhalb dieses JavaFX Application Thread erfolgen.[32]

Ereignisbehandlung[Bearbeiten | Quelltext bearbeiten]

Das Eventhandling von JavaFX ist die konsequente Weiterentwicklung der Ereignisbehandlung unter dem AWT und Swing beziehungsweise Java selbst, aber auch dem Web.[33] Moderne grafische Programme sind sehr stark ereignisorientiert.[34] Man benötigt deshalb Mechanismen, die auf das Auftreten von Ereignissen reagieren.

Ralph Steyer erklärt die Grundidee der Ereignisbehandlung folgendermaßen:

Ein Objekt kann ein Ereignisobjekt abfeuern und ein anderes Objekt registriert sich für eine Reaktion darauf (ein sogenannter Event-Listener), wie etwa beim Funken, bei dem ein Sender mit seinem Funkgerät auf einer bestimmten Frequenz eine Nachricht schickt und ein Empfänger, der sein Funkgerät auf diese Frequenz eingestellt hat, die Nachricht empfängt. Vollkommen analog kann der Empfänger auf eine Mitteilung über ein Ereignis reagieren, oder die Nachricht ignorieren. Im Zuhörerobjekt wird also über die konkrete Ereignisbehandlung entschieden.[35]

JavaFX-Events[Bearbeiten | Quelltext bearbeiten]

Das Paket javafx.event enthält die relevanten Klassen und Schnittstellen zur Ereignisbehandlung in JavaFX. Grundsätzlich ist ein konkretes Ereignis eine Instanz der Klasse javafx.event.Event beziehungsweise einer ihrer Unterklassen wie DragEvent, KeyEvent, MouseEvent oder ScrollEvent.[36]

Wenn ein Ereignis auftritt, kommt ein interner Mechanismus zum Einsatz, der bestimmt, welcher Node (Knoten) das Ziel eines Ereignisobjektes ist. Für Mausereignisse ist beispielsweise das Ziel der Node am Ort des Mauszeigers. Von dem selektierten Ereignisziel gibt es eine Ereignisversandkette (engl. event dispatch chain), die bis zur Wurzel des Szenengraphen hochgeht.

Zuerst wird immer versucht, das Ereignis im innersten Element, bei dem es aufgetreten ist, zu behandeln. Dies erfordert einen geeigneten Eventhandler (oder eine andere Behandlungsstruktur). Hat dieses Element keinen geeigneten Eventhandler, wird das Ereignisobjekt an das nächsthöhere Objekt im Baum weitergeleitet, usw. Man spricht in diesem Zusammenhang von Event-Bubbling, da das Ereignisobjekt wie eine Blase (engl. bubble) bis zur Wurzel des Szenengraphen aufsteigt. Wenn dieses bis zur Wurzel nicht behandelt werden kann, wird es vernichtet. Dies ist durchaus der Regelfall, da viele Ereignisse wie beispielsweise das verschieben des Mauszeigers um wenige Millimeter keine konkrete Reaktion der Applikation erzwingen.[37]

Eventhandler[Bearbeiten | Quelltext bearbeiten]

Wenn irgendein Node in der Route des Eventobjekts einen Eventhandler registriert hat, wird das Ereignis konsumiert. Die Aufgabe des Programmierers besteht also darin, das Ereignis entsprechend aufzufangen und die Reaktion auf dieses zu implementieren. Grundsätzlich implementieren Eventhandler die EventHandler-Schnittstelle, die das Überschreiben einer dort beschriebenen handle()-Methode erzwingt. Dort gehört dann die eigentliche Reaktion auf das aufgetretene Ereignis hin. Oft wird der Eventhandler als anonyme Klasse erstellt und registriert und dabei die handle()-Methode direkt implementiert, um die gewünschten Aktionen bereitzustellen. Diese Methode enthält dann als Parameter ein Ereignisobjekt vom jeweils relevanten Typ.[38]

Eine allgemeine Möglichkeit, um einem Node-Objekt einen Eventhandler hinzuzufügen bzw. abzumelden bieten die folgenden beiden Methoden[39]:

  • addEventHandler(EventType<T>, EventHandler<? super T>) zum Hinzufügen eines Handlers
  • removeEventHanlder(EventType<T>, EventHandler<? super T>) zum Abmelden eines Handlers.

Im ersten Parameter wird jeweils das konkrete Ereignis, auf das man reagieren will, spezifiziert, und im zweiten Parameter der Eventhandler selbst.

Für einen Button btn könnte das in etwa folgendermaßen aussehen[39]:

btn.addEventHandler(ActionEvent.ACTION, new EventHandler<ActionEvent>(){
	@Override public void handle(ActionEvent event)
	{
		// do something here
	}
});

Darüber hinaus bieten die Komponentenklassen auch eigene Setter-Methoden für spezifische Ereignisse an, die das folgende Format aufweisen:

setOnEventType(EventHandler handler)

Dabei gibt EventType den Typ des Ereignisses an. So gibt es beispielsweise für den Button die Methode setOnAction(EventHandler<ActionEvent>):

btn.setOnAction(new EventHandler<ActionEvent>(){
	public void handle(ActionEvent event)
	{
		// do something here
	}
});

Dynamische Datenstrukturen mit Änderungsmeldungen[Bearbeiten | Quelltext bearbeiten]

In JavaFX sind nicht nur einzelne Werte observierbar, sondern auch dynamische Datenstrukturen, die sich im Paket javafx.collections befinden: ObservableList, ObservableMap und ObservableSet leiten sich jeweils vom Observable Interface ab und fügen jeweils Methoden hinzu, um die passenden ChangeListener zu registrieren. Die neuen Datenstrukturen erweitern also die java.util-Datenstrukturen List, Set und Map und können Veränderungen melden.

Zu einer ObservableList existiert beispielsweise die Schnittstelle ListChangeListener, die auf Änderungen der observierten Liste reagiert. Die Klasse ListChangeListener.Change repräsentiert eine Änderung, die an einer solchen Liste vollzogen wird. Mit

observableList.addListener(new ListChangeListener(){/* do something here */});

wird dann der Listener für Veränderungen der Liste registriert.[40]

Funktionale Schnittstellen und Lambda-Ausdrücke[Bearbeiten | Quelltext bearbeiten]

Ein Lambda-Ausdruck ist eine namenlose (anonyme) Methode, die (als Objekt) weitergegeben werden kann. Der Begriff geht auf das Lambda-Kalkül zurück, eine formale Sprache zur Untersuchung von Funktionen (siehe auch funktionale Programmierung). Lambda-Ausdrücke in Java umfassen üblicherweise Parameterlisten, einen Rückgabetyp und einen Body:

(Parameterliste) -> {Anweisungen;}

Lambda-Ausdrücke beschreiben also Funktionsobjekte. Eine Funktion, die die Summe von zwei Argumenten liefert, lässt sich folgendermaßen ausdrücken:

(i,j) -> {i+j;}

Die Angabe der Parametertypen ist nur dann erforderlich, wenn der Compiler sie nicht selbst aus dem Kontext des Ausdrucks ableiten kann.[41] Lambda-Ausdrücke helfen, die oft schlecht lesbaren, langen Deklarationen innerer, anonymer Klassen, zu vermeiden.

In Java heissen Schnittstellen, die nur über eine Operation (abstrakte Methode) verfügen, funktionale Schnittstellen. Ein Funktions-Deskriptor beschreibt diese Methode. Eine abstrakte Klasse mit genau einer abstrakten Methode zählt allerdings nicht als funktionale Schnittstelle. Ein Lambda-Ausdruck ist ein Exemplar einer solchen funktionalen Schnittstelle. Es ist naheliegend, dass funktionale Schnittstellen genau eine abstrakte Methode vorschreiben, denn gäbe es mehrere, müsste ein Lambda-Ausdruck ja auch mehrere Implementierungen anbieten oder irgendwie eine Methode bevorzugen und andere vernachlässigen. Natürlich müssen auch Typen und Ausnahmen passen. Somit gibt es also nicht zu jeder Schnittstelle eine Abkürzung über einen Lambda-Ausdruck.[42]

Beispielsweise kann das Interface ActionListener als eine anonyme Klasse mit nur einer einzigen Methode implementiert werden, indem dessen abstrakte handle()-Methode überschrieben wird. Mit new wird dann ein Exemplar gebildet und entsprechend als Parameter übergeben (Siehe Abschnitt „Eventhandler“). Anstatt einer inneren anonymen Klasse kann nun ein Lambda-Ausdruck eingesetzt werden:

btn.setOnAction((event) -> {/*do something here*/});

Als Argument der Methode setOnAction(...) erfolgt nun nicht mehr eine vollständige Objektbildung mit new. Statt dessen werden der (beliebige) Bezeichner des Methodenarguments und die Anweisungen getrennt von einem Pfeiloperator -> notiert. Es wird also eine Kurzform der vollständigen Methodenimplementierung der aufgerufenen handle()-Methode notiert.[43]

Properties und Data Binding[Bearbeiten | Quelltext bearbeiten]

Properties und Data Binding sind zwei mächtige Sprach-Mechanismen in JavaFX, mit denen Beziehungen zwischen Variablen gestaltet werden können. Meist werden sie zur (gegenseitigen) Aktualisierung von Werten herangezogen. Der Benutzer bedient zum Beispiel einen Schieberegler, der die Breite eines Rechtecks regelt, und in Abhängigkeit des eingestellten Werts muss der width-Wert des Datenmodells aktualisiert werden und die Rechtecksfläche neu berechnet werden. Um die Daten miteinander abzugleichen, gibt es deshalb das Konzept von Properties und Data Binding.

Properties sind in JavaFX die Grundbausteine für die Verarbeitung und Kommunikation von Wertänderungen. Sie bilden die Basis für ein komfortables Data Binding. Ein Property ist ein Datencontainer, der zusätzlich Änderungsbenachrichtigungen ermöglicht. An Änderungen interessierte andere Klassen können sich als Listener registrieren. Man spricht bei einer Bindung auch von Abhängigkeiten beziehungsweise dependency.[44]

Die Binding-APIs werden in JavaFX in zwei Kategorien unterteilt[44][45]:

  • Das High-Level-API: Bietet für die meisten Situationen einen einfachen Weg zur Erstellung von Bindungen. Insbesondere wird hierfür in IDEs wie NetBeans eine Codevervollständigung bereitgestellt.
  • Das Low-Level-API: Dieses API ist sehr flexibel, schlank und schnell und bietet erweiterte Möglichkeiten, wenn das High-Level-API nicht ausreicht.

Im Package javafx.beans.property sind verschiedene Property-Klassen definiert, etwa zur Kapselung von int, long, float, double, boolean und String. Zur Änderungsbenachrichtigung implementieren die Properties das Interface Obervable bzw. ObervableValue<T>. So wird zum Beispiel anstatt des primitiven Datentyps double ein neuer Typ DoubleProperty verwendet, der den primitiven Typ double „einwickelt“. Bei den JavaFX-Properties gibt es neben den Getter- und Setter-Methoden noch eine zusätzliche Methode, die mit Property endet und das Property-Objekt zurückliefert.

Das folgende Beispiel stammt aus den Java-Dokumentationen von Oracle und definiert eine Klasse namens Bill (deutsch Rechnung), die eine einzige Property namens amountDue (deutsch fälliger Betrag) implementiert[45]:

package application;

import javafx.beans.property.DoubleProperty;
import javafx.beans.property.SimpleDoubleProperty;

class Bill
{
	// Definiere eine Variable um die Property zu speichern
    private DoubleProperty amountDue = new SimpleDoubleProperty();

    // Definiere die Getter-Methode für den Wert der Property
    public final double getAmountDue()
    {
    	return amountDue.get();
    }

    // Definiere die Setter-Methode für den Wert der Property
    public final void setAmountDue(double value)
    {
    	amountDue.set(value);
    }

    // Definiere einen Getter für die Property selbst
    public DoubleProperty amountDueProperty()
    {
    	return amountDue;
    }
}

Das amountDue-Objekt ist eine Instanz der Klasse javafx.beans.property.DoubleProperty. Um sie zu kapseln ist sie als private markiert. Entsprechend der Namenskonvention für den Zugriff auf Properties gibt es die folgenden Methoden:

  • Die getAmount()-Methode ist der standardmäßige Getter, der den aktuellen Wert der amountDue-Property zurückgibt. Der Rückgabewert dieser Methode ist double (und nicht etwa DoubleProperty). Die Getter-Methode sollte als final deklariert werden.
  • Die setAmount(double)-Methode ist ebenfalls als final deklariert und ermöglicht es, von außen den Wert der Property zu setzen. Ihr Parameter ist ebenfalls double.
  • Die amountDue()-Methode definiert den Getter der Property und gibt die Property selbst zurück. Sie ist eine neue Konvention, die sich aus dem Namen der Property (hier amountDue) und dem Wort Property zusammensetzt.

Properties sind insbesondere dann von Interesse, wenn man deren Veränderungen beobachtet. Im Ereignismodell von Java gibt es sogenannte Ereignisauslöser (Ereignisquellen, engl. event sources), wie zum Beispiel Schaltflächen oder Schieberegler. Diese Ereignisse können von Benutzern der grafischen Oberfläche stammen, aber auch auf eigene Auslöser zurückzuführen sein. Neben den Ereignisauslösern gibt es eine Reihe von Interessenten, sogenannte Listener, die informiert werden wollen, wenn ein bestimmtes Ereignis auftritt.[46] Zu den Properties existiert für diesen Fall ein ChangeListener (javafx.beans.value.ChangeListener), der über die Methode addListener() an die Property angehängt werden kann, die mit der entsprechenden Getter-Methode zurückgegeben wird.[47]

Zur Veranschaulichung eines ChangeListeners wird in den Java-Dokumentationen in der Main-Klasse eine Instanz electricalBill der Klasse Bill (siehe oben) erstellt[45]:

package application;

import javafx.beans.value.ObservableValue;
import javafx.beans.value.ChangeListener;

public class Main 
{
    public static void main(String[] args) 
    {
    	Bill electricBill = new Bill();
    	
    	electricBill.amountDueProperty().addListener(new ChangeListener<Object>(){
    		@Override public void changed(ObservableValue<?> o,Object oldVal, Object newVal)
    		{
    			System.out.println("Electric bill has changed!");
    		}
    	});

      electricBill.setAmountDue(100.00);

    }
}

Als Ausgabe erscheint in der Konsole Electric bill has changed!. Der Listener hat also bemerkt, dass mit electricBill.setAmountDue(100.00) der Wert der amountDue-Property geändert wurde und die entsprechende Nachricht über die changed(...)-Methode ausgegeben.

Die High-Level-APIs sind der einfachste und schnellste Weg, um Bindings einzusetzen. Sie bestehen aus zwei Teilen: dem Fluent-API und der Binding-Klasse. Das Fluent-API stellt zahlreiche Methoden auf abhängigen Objekten bereit, während die Binding-Klasse statische Factory-Methoden anbietet.

Im folgenden Beispiel werden zwei Integers so gebunden, dass ihre Werte immer automatisch in der Summe sum addiert werden[45]:

package application;

import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.binding.NumberBinding;

public class Main
{
    public static void main(String[] args)
    {
        IntegerProperty num1 = new SimpleIntegerProperty(1);
        IntegerProperty num2 = new SimpleIntegerProperty(2);

        NumberBinding sum = num1.add(num2);

        System.out.println(sum.getValue());

        num1.set(2);

        System.out.println(sum.getValue());
    }
}

Es gibt insgesamt drei Variablen, nämlich die beiden abhängigen Variablen num1 und num2 und die Bindung sum. Die abhängigen Variablen sind beide vom Typ IntegerProperty und die Bindung selbst ist vom Typ NumberBinding. Der Wert von sum ändert sich also automatisch, wenn sich num1 oder num2 ändern.

Deklarative GUI-Beschreibungen[Bearbeiten | Quelltext bearbeiten]

Grundsätzlich können grafische Oberflächen über eine Programm-API aufgebaut werden, oder aber in einer deklarativen Beschreibung spezifiziert werden. Bei deklarativen Oberflächen wird die Anordnung der Komponenten in einer externen Ressourcendatei beschrieben.

FXML[Bearbeiten | Quelltext bearbeiten]

Neben der Möglichkeit, den Szenengraphen über den Programmcode aufzubauen, bietet JavaFX auch die Möglichkeit, die Objekte über XML zu konfigurieren. Mit FXML stellt JavaFX eine einfach zu erlernende, deklarative Sprache zur Verfügung, die eine alternative Definition von grafischen Oberflächen rein über XML erlaubt.[48] Da XML hierarchisch strukturiert ist, kann die grundlegende hierarchische Gliederung einer GUI in Containern und Komponenten sehr gut auf XML-Basis abgebildet werden. Dies macht es auch einfacher, das Layout sauber vom Code zu trennen. Darüber hinaus können dort Web-Technologien wie CSS (Cascading Style Sheets), JavaScript aber auch andere Sprachen wie Groovy eingesetzt werden, indem sie in den XML-Code eingebettet und damit verknüpft werden.[49]

Zum Laden einer FXML-Ressource kommt die Klasse javafx.fxml.FXMLLoader und dessen Klassenmethode load(...) zum Einsatz. Hier muss der relative Pfad zur *.fxml-Datei als Parameter übergeben werden. Nun kann die angegebene Datei als Ressource geladen werden und daraus ein Objekt vom Typ javafx.scene.Parent erzeugt werden. Dieses wird dem Konstruktor des Scene-Objekts als Parameter übergeben.[50]

In den Java-Dokumentationen wird der Unterschied zwischen Code und FXML am folgenden einfachen Beispiel veranschaulicht[51]:

Der folgende Programmcode baut eine grafische Oberfläche auf, die aus einem BorderPane besteht, das oben das Label mit der Beschriftung Page Title enthält und im Zentrum ein Label mit der Beschriftung Some data here:

BorderPane border = new BorderPane();
Label toppanetext = new Label("Page Title");
border.setTop(toppanetext);
Label centerpanetext = new Label ("Some data here");
border.setCenter(centerpanetext);

Dieselbe Oberfläche wird in FXML folgendermaßen beschrieben:

<BorderPane>
    <top>
        <Label text="Page Title"/>
    </top>
    <center>
        <Label text="Some data here"/>
    </center>
</BorderPane>

Die hierarchische Struktur der Oberfläche kann also sehr gut in der hierarchisch strukturierten Auszeichnungssprache FXML dargestellt werden. Dies macht es einfacher, Komponenten hinzuzufügen und die Gliederung einer GUI aufzubauen.

Der Scene Builder[Bearbeiten | Quelltext bearbeiten]

Der JavaFX Scene Builder ist ein grafisches Tool, das die Erstellung von FXML-Dateien vereinfacht. Mit dem Tool können GUI-Elemente ohne Programmierkenntnisse entworfen werden. Der Anwender kann per Drag and Drop die XML-Strukturen von FXML visuell gestalten und generieren lassen.[52]

Oracle hat die Entwicklung des Tools eingestellt und den Quelltext des Programms unter einer BSD-ähnlichen Lizenz freigegeben.[53] Daraufhin hat die Firma Gluon die Wartung und den kommerziellen Support übernommen.[54]

FXGraph[Bearbeiten | Quelltext bearbeiten]

FXGraph ist eine einfache DSL (Domain Specific Language) zur Definition des Objektgraphen, der im Hintergrund in FXML umgesetzt wird. FXGraph stammt aus dem Projekt e(fx)clipse, eine JavaFX-Untestützung in Eclipse.[55] FXGraph ist kompakter als FXML und erinnert entfernt an JSON.[56]

Kritik[Bearbeiten | Quelltext bearbeiten]

Der ehemalige Sun-Mitarbeiter und Codename-One-Gründer Shai Almog bescheinigt JavaFX eine wenig rosige Zukunft. Er teilt JavaFX-Nutzer in drei Kategorien: Unternehmen mit grossen Investitionen in Swing, Studenten und eingefleischte Fans. Auf diesem Fundament lasse sich laut Almog nur schwer eine lebhafte Community aufbauen. Außerdem sende Oracle keine klaren Signale aus, wie es um sein zukünftiges Engagement für JavaFX bestellt sei. Insgesamt macht er für die mangelnde Zukunft von JavaFX drei Hauptgründe verantwortlich:

  • Oracle selbst nutzt JavaFX nicht bzw. nicht in ausreichendem Maße: Selbst Swing-basierte Produkte bewegen sich nicht in Richtung JavaFX. Zudem wird der Scene Builder seit einiger Zeit nicht mehr von Oracle selbst vertrieben.
  • JavaFX hat nie denselben Einfluss wie Swing gewonnen. Die Hauptzielgruppe von JavaFX, nämlich die Swing-Entwickler, seien nicht auf die neue Technologie umgestiegen.
  • Der Jobmarkt sehe düster aus: Auf der Karriereseite dice.com fand Almog nur 28 Stellen, die JavaFX-Kenntnisse verlangten, im Gegensatz zu 198 Stellenangebote für Swing, 2333 für Android und 16752 für Java EEE (Stand 22. November 2015).[57]

Nachdem der Support für die ARM Embedded Platform und die Entwicklung des Scene Builders von Oracle eingestellt wurden, forderte unter anderem der iJUG-Verbund (Interessenverbund deutscher Java User Groups) von Oracle ein explizites Bekenntnis zu JavaFX.[58] Daraufhin stellte Don Smith (Oracle Senior Director Product Management) klar, dass JavaFX auch weiterhin die empfohlene Technologie für die Entwicklung von Rich Clients sei und diesbezüglich auch weiterentwickelt werde. Der wegfallende Support der ARM-Plattform habe mit dem hohen Aufwand zu tun, angesichts einer sich sehr schnell verändernden Hardware-Technik einen nachhaltigen kommerziellen ARM-Support zu garantieren. Der Scene Builder sei unter der offenen BSD-Lizenz verfügbar gemacht worden und die Strategie bestehe nun darin, den Scene Builder in Tools und Entwicklungsplattformen zu integrieren. Smith verweist insbesondere auf das Startup Gluon, das sich mit JavaFX-Ports und dem Scene Builder befasst.[59]

Insgesamt steht Java in Konkurrenz mit zahlreichen anderen Technologien: Auf der Serverseite beispielsweise mit Node.js und Ruby on Rails, auf Mobile-Seite mit iOS und in den Bereichen Mobile und Desktop mit HTML und JavaScript.[57] Ob sich JavaFX als Technologie für Web-Oberflächen durchsetzen wird, muss die Zeit noch zeigen.

Einige Experten sehen für JavaFX insbesondere eine Nische im Bereich mächtiger Desktop-Clients mit anspruchsvoller grafischer Interaktion, in der es sich dauerhaft etablieren könnte. So sehen sie die Stärken des Frameworks nicht zuletzt bei der Entwicklung hybrider Desktopanwendungen. Auch jeder, der einen Client mit direktem Zugriff auf lokale Ressourcen (Dateisystem, serielle Ressourcen, usw.) entwickelt, sei mit JavaFX gut aufgehoben.[59][60]

Literatur[Bearbeiten | Quelltext bearbeiten]

  • Anton Epple: JavaFX 8. Grundlagen und fortgeschrittene Techniken. dpunkt.verlag: Heidelberg, 2015.
  • Ralph Steyer: Einführung in JavaFX. Moderne GUIs für RIAs und Java-Applikationen. Springer Vieweg: Wiesbaden, 2014.
  • Christian Ullenboom: Java ist auch eine Insel. Einführung, Ausbildung, Praxis. 11. Auflage, Galileo Press: Bonn, 2014, insb. S. 1009-1063.
  • Christian Ullenboom: Java SE 8 Standard-Bibliothek. Das Handbuch für Java-Entwickler. 2. Auflage, 2014, Galileo Press: Bonn, 2014, insb. S. 1031-1076.

Weblinks[Bearbeiten | Quelltext bearbeiten]

Einzelnachweise und Anmerkungen[Bearbeiten | Quelltext bearbeiten]

  1. Ullenboom: Java ist auch eine Insel. 11. Auflage, 2014, S. 1011.
  2. JavaFX FAQ. Abgerufen am 29. Feb. 2016.
  3. a b c Ullenboom: Java ist auch eine Insel. 11. Auflage, 2014, S. 1011.
  4. JavaFX 1.0 is live
  5. JavaFX 1.3 Veröffentlichung (Memento vom 30. April 2011 im Internet Archive)
  6. javafx.com
  7. Neuerungen in JavaFX 2.0. Netzwelt, abgerufen 13. Oktober 2011
  8. a b Ullenboom: Java ist auch eine Insel. 11. Auflage, 2014, S. 1012.
  9. Hendrik Ebbers: JavaFX8 - Was ist neu? In: jaxenter (erstellt am 20. März 2014, abgerufen am 12. Dezember 2016).
  10. JDK for ARM 8u33 release notes. Oracle. 16. Februar 2013. Abgerufen am 29. Februar 2016: „Starting with JDK 8u33, JavaFX Embedded is removed from the ARM bundle and is not supported.
  11. Steyer: Einführung in JavaFX. 2014, S. 166-167.
  12. Oracle: JavaFX Architecture In: http://docs.oracle.com (zulätzt geändert 2013, abgerufen am 14. Dezember 2016)
  13. Anmerkung: Nicht zu verwechseln mit der Geheimdienstsoftware PRISM
  14. a b c Steyer: Einführung in JavaFX. 2014, S. 8.
  15. Gerrit Grunwald: Visualisierung in Java mit JavaFX In: heise Developer (erstellt am 28. Juni 2013, abgerufen am 14. Dezember 2016).
  16. Steyer: Einführung in JavaFX. 2014, S. 8-9.
  17. Anmerkung:Die main()-Methode ist bei einer JavaFX-Applikation im Grunde nicht notwendig, während sie bei einer normalen Java-Applikation ja den zentralen Einstiegspunkt darstellt. Sie wird von NetBeans nur zur Sicherheit generiert, um im Fall mangelnder JavaFX-Unterstützung auf Zielplattformen den Start der Applikation zu gewährleisten. Netbeans selbst ignoriert die main()-Methode. Siehe Steyer: Einführung in JavaFX. 2014, S. 29.
  18. Ullenboom: Java SE 8 Standard-Bibliothek. 2. Auflage 2014, S. 1032.
  19. Oracle: javafx.application - Class Application auf docs.oracle.com (abgerufen am 11. Dezember 2016); Epple: JavaFX 8. 2015, S. 9-10.
  20. Anmerkung: Der Grund dafür ist, dass die init-Methode - genau wie der Konstruktor der Klasse - noch vom Launcher-Thread der Anwendung aufgerufen wird. UI-Elemente dürfen aber nur im JavaFX-Application-Thread erzeugt und modifiziert werden. Siehe Epple: JavaFX 8. 2015, S. 10.
  21. a b Steyer: Einführung in JavaFX. 2014, S. 29.
  22. Epple: JavaFX 8. 2015, S. 11.
  23. Für eine ausführliche Beschreibung der Klasse Stage siehe Oracle: Class Stage auf docs.oracle.com (abgerufen am 11. Dezember 2016). Siehe auch Epple: JavaFX 8. 2015, S. 11-13.
  24. Steyer: Einführung in JavaFX. 2014, S. 29, 65.
  25. Epple: JavaFX 8. 2015, S. 13.
  26. Oracle: Class Scene auf docs.oracle.com (abgerufen am 11. Dezember 2016).
  27. Ullenboom: Java SE 8 Standard-Bibliothek. 2. Auflage, 2014, S. 1033.
  28. Oracle: Class Group auf docs.oracle.com (abgerufen am 11. Dezember 2016); Ullenboom: Java SE 8 Standard-Bibliothek. 2. Auflage, 2014, S. 1034-1035.
  29. Oracle: Class Control auf docs.oracle.com (abgerufen am 11. Dezember 2016); Ullenboom: Java SE 8 Standard-Bibliothek. 2. Auflage, 2014, S. 1034.
  30. Ullenboom: Java SE 8 Standard-Bibliothek. 2. Auflage, 2014, S. 1036.
  31. Epple: JavaFX 8 2015, S. 43-44; Oracle: Using JavaFX UI Controls auf docs.oracle.com (abgerufen am 11. Dezember 2016)
  32. Jeff Friesen: Exploring JavaFX's Application class In: JavaWorld (erstellt am 14. April 2016, abgerufen am 13. Dezember 2016).
  33. Steyer: Einführung in JavaFX. 2014, S. 201.
  34. Anmerkung: Im Unterschied dazu sind konsolenbasierte oder ältere grafische Programme oft eine lineare bzw. deterministische Folge von Anweisungen und/oder Eingaben, die nacheinander abgearbeitet werden.
  35. Steyer: Einführung in JavaFX. 2014, S. 201.
  36. Steyer: Einführung in JavaFX. 2014, S. 201.
  37. Steyer: Einführung in JavaFX. 2014, S. 202-205.
  38. Steyer: Einführung in JavaFX. 2014, S. 205-209.
  39. a b Ullenboom: Java SE 8. Standard-Bibliothek. 2. Auflage, 2014, S. 1037.
  40. Steyer: Einführung in JavaFX. 2014, S. 193-195; Ullenboom: Java SE 8 Standard-Bibliothek. 2. Aufl. 2014, S. 379-388; Epple: JavaFX 8. 2015, S. 22-23.
  41. Martin Gerlach: Java SE 8 Neuerungen (Teil 1): Lambda-Ausdrücke und Default-Methoden In: Neo Tech Blog (erstellt am 17. November 2014, abgerufen am 16. Dezember 2016).
  42. Ullenboom: Java SE 8 Standard-Bibliothek. 2. Aufl. 2014, S. 63.
  43. javabeginners: Was sind Lambda Ausdrücke (lambda expressions)? In: https://javabeginners.de (Letzte Änderung am 3. Juli 2016, abgerufen am 16. Dezember 2016); Marco Jakob: JavaFX 8 Event Handling Examples In: code.makery - Learning how to code (erstellt am 3. Mai 2014; abgerufen am 16. Dezember 2016).
  44. a b Steyer: Einführung in JavaFX. 2014, S. 225.
  45. a b c d Oracle: JavaFX: Properties and Binding Tutorial In: docs.oracle.com (abgerufen am 13. Dezember 2016).
  46. Ullenboom: Java SE 8 Standard-Bibliothek. 2. Aufl. 2014, S. 806-807.
  47. Steyer: Einführung in JavaFX. 2014, S. 228-231.
  48. Anmerkung: Dies ist vergleichbar mit XAML (Extensible Application Markup Language) aus dem .NET-Framework von Microsoft.
  49. Steyer: Einführung in JavaFX. 2014, S. 9-10; Ullenboom: Java SE 8 Standard-Bibliothek. 2. Aufl. 2014, S. 1062-1063; Ullenboom: Java ist auch eine Insel. 11. Auflage, 2014, S. 1013-1014.
  50. Steyer: Einführung in JavaFX. 2014, S. 65-66.
  51. Oracle: Mastering FXML In: http://docs.oracle.com (Update 2014, abgerufen am 14. Dezember 2016).
  52. Das Tool ist unter folgender URL für Windows, OS X und Linux erhältlich: http://gluonhq.com/labs/scene-builder/
  53. Simon Vienot: openjfx-dev Mailing Liste. "Scene Builder is now open source!". 3. Dez. 2013. Abgerufen am 29. Mär. 2016.
  54. Gluon supports Scene Builder. 4. Mär. 2015. Abgerufen am 29. Mär. 2016.
  55. Tom Schindl: FXGraph In: https://www.eclipse.org/ (zuletzt geändert am 9. Dezember 2013; abgerufen am 13. Dezember 2016).
  56. Ullenboom: Java ist auch eine Insel. 11. Auflage, 2014, S. 1014.
  57. a b Shai Almog: Should Oracle Spring Clean JavaFX? In: DZone (erstellt am 22. November 2015, abgerufen am 14. Dezember 2016); siehe auch Michael Thomas: Ruhe in Frieden, JavaFX? In: JAXenter (erstellt am 24. November 2015, abgerufen am 14. Dezember 2016).
  58. iJUG: iJUG fordert von Oracle ein klares Bekenntnis zu JavaFX In: iJUG (erstellt am 27. Januar 2016; Update 2. Februar 2016; abgerufen am 14. Dezember 2016)
  59. a b Hartmut Schlosser: Hart aber Fair: Welche Zukunft hat JavaFX? In: JAXenter (erstellt am 22. März 2016, abgerufen am 14. Dezember 2016).
  60. JAXenter, Interview mit Alexander Casall: „Nur Chuck Norris kann hybride Desktopanwendungen“ In: JAXenter (erstellt am 21. April 2015, abgerufen am 14. Dezember 2016).