e(fx)clipse: JavaFX-Tooling für Eclipse

Eclipse meets JavaFX

Marc Teufel

Es tut sich was in der Eclipse-UI-Welt: Dank der reichhaltigen Möglichkeiten von e(fx)clipse zieht JavaFX mit Pauken und Trompeten in die bisher klar von SWT dominierte Eclipse-Welt ein – und erobert dabei die Herzen der Entwickler im Sturm.

Vor noch gar nicht langer Zeit war die Welt der Entwickler von Java-basierten Rich Clients noch in Ordnung: Das GUI wurde entweder mit Swing oder SWT entwickelt. Fertig. Doch die Zeiten ändern sich. Insbesondere HTML5 brachte diese schöne heile Welt der Java-UI-Technologien durcheinander, denn früh stand fest: Swing und SWT können es mit der Konkurrenz nicht aufnehmen. Oracle reagierte darauf mit der Veröffentlichung von JavaFX 2 und positionierte es als Nachfolger von Swing. Diese neue Technologie hat bis auf den Namen nahezu nichts mehr mit dem Vorgänger JavaFX gemeinsam. Mit JavaFX 2 scheint es Oracle jedoch tatsächlich gelungen zu sein, eine neue Java-UI-Technologie auf dem Markt zu platzieren, die nicht nur einen großen Teil der Entwicklergemeinde fasziniert und mitreißt, sondern tatsächlich auch das Zeug hat, es mit der Konkurrenz aufzunehmen.

JavaFX 2 überzeugt nicht nur durch sein schickes und modernes Aussehen, sondern punktet vor allem mit seinem durchdachten Gesamtkonzept. Das fängt bei elementaren Dingen wie seiner Architektur an – also damit, wie man eine Anwendung mit JavaFX 2 aufbaut, geht weiter über das detaillierte und umfangreiche CSS Styling bis hin zu der Möglichkeit, mithilfe von FXML deklarative UIs bauen zu können. Während die NetBeans IDE schon bald mit einer ersten Unterstützung von JavaFX 2 punkten konnte, begann man bei Eclipse erst im Sommer letzten Jahres aktiv mit der Entwicklung eines entsprechenden Toolings. Das maßgeblich von der Firma BestSolution.at angetriebene Projekt e(fx)clipse [1] bringt dabei nicht einfach nur umfangreiches Tooling zum Entwickeln von JavaFX 2 nach Eclipse. Es geht noch einen Schritt weiter, indem es JavaFX selbst erweitert (Stichwort FXGraph) und außerdem JavaFX 2 in Eclipse-Technologien integriert. e(fx)clipse bringt Unterstützung für folgende Teilbereiche von JavaFX mit:

  • Erweiterungen in JDT/PDE
  • FXML Editor
  • Live Preview
  • CSS Editor
  • FXGraph
  • Eclipse 4 Renderer für JavaFX 2
Erweiterungen in JDT/PDE

Wie man in Abbildung 1 sehen kann, hält e(fx)clipse eine Vielzahl von Wizards bereit. Das Spektrum reicht dabei vom Erstellen einfacher JavaFX-Anwendungen über OSGi-Applikationen bis hin zu Eclipse-4-Anwendungen mit JavaFX-Unterstützung. Als Grundlage stellt e(fx)clipse in diesem Zusammenhang für Java-Projekte zunächst einmal einen eigenen Classpath-Container bereit, der auf alle benötigten Libraries von JavaFX 2 verweist. Erst mit dieser JDT-Erweiterung gelingt die Integration von JavaFX in den berühmten Eclipse-Code-Editor problemlos. JavaFX-Anwendungen lassen sich damit grundsätzlich genauso programmieren, wie es mit Swing oder SWT auch möglich ist. Die JDT-Erweiterungen gehen natürlich noch weiter. Zusätzlich zum JavaFX-Classpath-Container und einem Wizard zum Anlegen von JavaFX-Projekten soll an dieser Stelle unbedingt auch auf die hervorragende Integration des (auf Ant basierenden) Build-Prozesses von JavaFX-Anwendungen in JDT hingewiesen werden. Grundsätzlich bringt JavaFX schon Ant-Tasks zum Bauen, Signieren und Deployen von JavaFX-Anwendungen mit. e(fx)clipse setzt darauf auf und führt ein neues Konfigurationsformat mit der Dateiendung .fxbuild mitsamt Editor ein, mit dem der Build- und der Deployment-Prozess sehr komfortabel verwaltet werden können. Abbildung 2 zeigt den besagten Konfigurationseditor. Auf Grundlage solcher .fxbuild-Konfigurationen ist der Entwickler später in der Lage, quasi auf Knopfdruck Ant-Files zu generieren, die ihrerseits die mit JavaFX gelieferten Ant-Tasks verwenden. Das .fxbuild-Format ist somit also ein (im Kern auf XML basierendes) besseres Properties-File – die Magie kommt jedoch von JavaFX selbst! Die Erweiterungen betreffen nicht nur JDT; auch PDE hat einen ähnlichen Classpath-Container – den so genannten PDEClasspath-Container – spendiert bekommen. Erst so lassen sich Equinox-Anwendungen und Plug-in-Projekte mit JavaFX-Unterstützung in der Eclipse-IDE programmieren.

Abb. 1: e(fx)clipse stellt eine Vielzahl von Wizards für Java FX 2 bereit

Abb. 2: e(fx)clipse erleichtert das Bauen, Signieren und Ausliefern von JavaFX-Anwendungen durch Editoren, mit denen sich Ant-Files erzeugen und ausführen lassen

Deklarative Oberflächen mit FXML

JavaFX 2 ist zweifelsohne eine moderne UI-Technologie. Zu Zeiten von Swing und SWT wurden die Oberflächen ausschließlich mit Code aufgebaut. Egal, ob man das UI per Hand programmierte oder einen GUI-Editor wie WindowBuilder bediente – am Ende stand immer Sourcecode, der das UI definierte. Moderne Oberflächentechnologien wie beispielsweise WPF (Windows Presentation Foundation) aus dem Microsoft-Universum dagegen verfolgen einen ganz anderen Ansatz: Hier werden UIs in einer XML-Syntax definiert und mit einer Controller-Klasse verbunden, die dann die Methoden für das Event Handling enthält. Die Definition der Oberfläche und die Ereignisbehandlung sind also strikt getrennt. Mit FXML kommt diese Idee nun auch endlich im Rahmen von JavaFX in Java an. Abbildung 3 zeigt eine typische FXML-Datei im FXML-Editor, den e(fx)clipse ebenfalls mitbringt. Zu Beginn des abgebildeten FXML stehen einige Importanweisungen für alle im Code verwendeten JavaFX-Elemente. Es wird ein Szenegraph vom Typ Scene aufgebaut. Die beiden Attribute deklarieren dabei den JavaFX-Namensraum fx, und über das Attribut fx:controller erfolgt die Verknüpfung mit der zugehörigen Java-Controller-Klasse. Die Java-Klasse ist hier mit ihrem vollqualifizierenden Klassennamen anzugeben. Im weiteren Verlauf werden zusätzliche Controls in den Szenegraphen aufgenommen und entsprechend konfiguriert. Wichtig ist an dieser Stelle auf das Attribut fx:id hinzuweisen: Über diese ID lassen sich später im zugehörigen Java-Controller auf die einzelnen Controls programmatisch zugreifen. Neben dem eigentlichen FXML-Editor gibt es zum Anlegen neuer FXML-Definitionen natürlich auch einen eigenen Wizard. Nach Abschluss dieses Wizards wird das soeben erstellte Dokument automatisch im FXML-Editor geöffnet. Dieser Editor kennt alle Elemente, die Bestandteil eines FXML-Dokuments werden können, und bietet hierfür eine umfangreiche Codevervollständigung an. Diese Codevervollständigung hilft nicht nur beim Schreiben von FXML-Tags und Attributen, sondern fügt auch bei der ersten Verwendung eines bisher noch nicht ins Dokument importierten Controls den entsprechenden Importbefehl automatisch ein. Zusätzlich ist der FXML-Editor tief mit JDT verwurzelt. So werden beim Verknüpfen von FXML mit dem Java-Controller über das Attribut fx:controller auch gleich alle infrage kommenden Java-Klassen samt Java Doc zur Auswahl angeboten. Andersherum stellt der FXML-Editor fest, wenn ein Verweis auf eine zuvor angegebene Java-Klasse nicht aufgelöst werden kann, zum Beispiel, wenn die referenzierte Java-Klasse unter dem eingetragenen Namen nicht verfügbar ist. Abbildung 3 unterstreicht auch, wie weit die Integration mit JDT tatsächlich geht: Alle Zeilen im XML-Listing, die direkt auf entsprechende Stellen in der zugehörigen Java-Controller-Klasse verweisen, aber dort noch nicht verfügbar sind, sind farblich markiert. Selbstverständlich bietet e(fx)clipse an dieser Stelle Quick Fixes an, mit denen sich die fehlenden Attribute und Methoden in der Controller-Klasse automatisch erzeugen lassen. Listing 1 zeigt exemplarisch, wie der zugehörige Controller für das FXML-Dokument aus Abbildung 3 implementiert werden kann. Über die Annotation @FXML sind alle Bestandteile der Klasse markiert, die in Verbindung mit dem FXML-Dokument stehen. Dabei müssen die Namen der Felder mit den entsprechenden IDs, die im Dokument definiert sind, übereinstimmen. Erst so wird es möglich, dass das im Controller verwendete Label alle Eigenschaften von dem im FXML-Dokument definierten Label übernehmen kann. Das gleiche gilt für die Ereignisbehandlung. Eine Methode, die ein Ereignis verarbeiten soll, ist ebenso mit der Annotation @FXML zu markieren, und der Methodenname muss identisch sein mit der Angabe im FXML-Dokument.

Listing 1
package net.teufel.javafx;

import java.text.SimpleDateFormat;
import java.util.Date;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.Button;

public class HelloWorldFxmlController {

@FXML Label labelTitel;
@FXML Button buttonDatum;
@FXML Button buttonZeit;

@FXML
public void datumAnzeigen() {
labelTitel.setText(new SimpleDateFormat("dd.MM.yyyy").format(new Date()));
}

@FXML
public void zeitAnzeigen() {
labelTitel.setText(new SimpleDateFormat("HH:mm:ss").format(new Date()));
}
}

Abb. 3: e(fx)clipse hat einen gut in JDT integrierten Editor für FXML-Dokumente an Bord

[ header = Eclipse meets JavaFX – Teil 2 ]

Live Preview

Eine weitere sehr hilfreiche View, die e(fx)clipse anbietet, ist die so genannte „JavaFX Preview“ (Abb. 4). Wird diese View aktiviert, zeigt sie jeweils eine Vorschau des UIs an, das man gerade im FXML-Editor bearbeitet. Mit jedem Speichervorgang aktualisiert sich auch die Preview-Ansicht. Bei etwaigen Fehlern kann natürlich keine Vorschau angezeigt werden. Stattdessen hat man dann aber die Möglichkeit, in den Reiter Error log zu wechseln, wo ein entsprechender Strack Trace angezeigt wird. Aus diesem kann man meist sehr leicht herauslesen, was beim Erzeugen der Vorschau schief gelaufen ist. Sehr schön ist in der JavaFX Preview auch die Möglichkeit, einen eventuell schon im FXML definierten Controller aktiv zu schalten (dies erfolgt mit einem der beiden Toolbar-Schalter oben). Wird der Controller hinzugeschaltet, sieht man nicht nur die Anwendung in der Vorschau, man kann auch mit dieser interagieren. So wird die Ereignisverarbeitung eines Knopfes ausgeführt, wenn man diesen in der Vorschau drückt. Auf diese Weise kann man sich das ständige Neustarten der Anwendung zum Testen bestimmter Änderungen sparen, weil man direkt in der Vorschau viel ausprobieren kann.

e(fx)clipse bringt keinen GUI-Builder für JavaFX-Oberflächen in der Art mit, wie ihn beispielsweise WindowBuilder anbietet. Es beschränkt sich aktuell ausschließlich auf die Unterstützung von JavaFX auf Code-, FXML- und DSL-Ebene und bietet darüber hinaus die soeben beschriebene Vorschauansicht an. Ein „Zusammenklicken“ von JavaFX-Anwendungen ist mit e(fx)clipse dagegen nicht möglich. Leider bietet auch der WindowBuilder aktuell keine Unterstützung für JavaFX an, und zum gegenwärtigen Zeitpunkt ist auch keine aktive Entwicklung in diese Richtung zu erkennen. Wenn sich JavaFX jedoch weiter in der Geschwindigkeit verbreitet, wie es aktuell der Fall ist und das Interesse an dieser neuen UI-Technologie weiter wächst, dann wird sicherlich auch der WindowBuilder schon bald mit einer entsprechenden Erweiterung aufwarten können.

Abb. 4: Die Live Preview in Aktion

CSS

Die Idee, Oberfläche mithilfe von CSS zu gestalten, ist nicht neu. In Eclipse 4 sind bereits ähnliche Möglichkeiten für SWT enthalten. Das Problem hier ist nur, dass man mit CSS zwar viel gestalten kann, es aber doch technische Grenzen gibt. So ist es mit dem CSS-Styling-Feature aus Eclipse 4 nicht möglich, eine pixelgenaue Umsetzung eines Designs etwa bei Menüs oder Buttons zu erreichen. In JavaFX 2 gibt es ebenso die Möglichkeit, die Gestaltung mit CSS vorzunehmen. Im Gegensatz zu seinem Eclipse-4-Pendant sind die Möglichkeiten hier aber viel reichhaltiger, es gibt nahezu keine Einschränkungen. Die Abbildung eines pixelperfekten Designs sollte mit dem JavaFX-Styling-Feature problemlos machbar sein. In JavaFX gibt es gleich mehrere Möglichkeiten, CSS-Code zu hinterlegen. So bietet jedes Control zunächst einmal mit der Methode setStyle() die Möglichkeit, CSS direkt zu setzen:

labelTitel.setStyle("-fx-font-size: 12px; 
-fx-font-weight: bold;
-fx-text-fill: #333333;
-fx-effect: dropshadow( gaussian , rgba(255,255,255,0.5) , 0,0,0,1 ); ");

Ferner gibt es die Möglichkeit, CSS-Styling über das Style-Attribut, wie man auch in Abbildung 3 am Beispiel des Labels sehen kann, direkt in ein FXML-Dokument zu schreiben. Ist die zuvor beschriebene Vorschauansicht aktiviert, werden auch CSS-Veränderungen im Style-Attribut erkannt und angezeigt. Beim Schreiben von CSS-Attributen im FXML-Editor gibt es leider keine direkte Unterstützung.

Die letzte und wahrscheinlich am weitesten verbreitete Möglichkeit, CSS-Regeln mit der Oberfläche zusammenzubringen, ist es, diese in einer separaten Datei unterzubringen und dann beim Start der Anwendung einzulesen und zu aktivieren. Listing 2 zeigt einen solchen Anwendungsstarter, der sowohl FXML- als auch CSS-Datei in einer Scene zusammenbringt.

Listing 2
package net.teufel.javafx;

import java.io.IOException;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.stage.Stage;

public class HelloWorldFxml extends Application {

@Override
public void start(Stage primaryStage) {
primaryStage.setTitle("FXML Hello World Application");
try {
Scene scene =
(Scene)FXMLLoader.load(getClass().getResource("HelloWorldFxml.fxml"));
scene.getStylesheets().add(getClass()
.getResource("design.css").toExternalForm());
primaryStage.setScene(scene);
} catch (IOException e) {
e.printStackTrace();
}
primaryStage.show();
}

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

Zum Editieren solcher CSS-Dateien bringt e(fx)clipse einen leistungsfähigen CSS-Editor mit (Abb. 5). Weil dieser alle Attribute kennt, die verwendet werden können, wird das Schreiben von CSS-Regeln für Java FX-Anwendungen zum Kinderspiel. Ist die CSS-Datei – wie in Listing 2 gezeigt – in die Anwendung eingebunden, kann die Preview zunächst noch keine Vorschauansicht anzeigen, weil der Eclipse IDE die Verknüpfung noch nicht bekannt ist. Um dies zu bewerkstelligen, ist folgende Zeile zusätzlich ins FXML-Dokument aufzunehmen:

<?scenebuilder-stylesheet design.css?>

Abb. 5: Der CSS-Editor zeigt alle verfügbaren CSS-Attribute an

FXGraph

Bei FXGraph handelt es sich nicht um ein Feature, das der JavaFX-Standard mitbringt. Vielmehr hat man es hier mit einer Erweiterung für JavaFX zu tun, die man im Rahmen von e(fx)clipse erhält. FXGraph ist im Kern eine eigene, kleine DSL zum einfachen Schreiben von JavaFX-Oberflächen. Die Syntax erinnert dabei an einen Mix aus Java und Groovy und ist sehr leicht verständlich. In FXGraph geschriebene Oberflächen werden zur Entwicklungszeit von e(fx)clipse ausgewertet; nach jedem Speichervorgang wird aus dem FXGraphen ein FXML-Dokument generiert beziehungsweise aktualisiert. Darauf aufbauend wird umfangreiche Codevervollständigung angeboten. Dabei wird nicht nur die FXGraph-eigene Syntax berücksichtigt, sondern auch auf JDT zurückgegriffen. Ist beispielsweise ein Controller eingebunden, zeigt die Codevervollständigung des FXGraph-Editors beim Zuweisen einer Methode, etwa beim onAction-Attribut eines Buttons, alle Methoden aus dem Controller an, die zur Verfügung stehen. Auch die Live Preview ist in der Lage, den FXGraphen in der Vorschauansicht anzuzeigen. Auf einfache Weise können hier externe CSS-Dateien und sonstige Ressourcen in den FXGraphen eingebunden werden. Das ist insbesondere beim CSS-Styling von großem Wert, weil so die CSS-Regeln extern gehalten werden können, die Live Preview diese aber trotzdem erkennen und darstellen kann. Dies erleichtert das Testen von CSS-Styling erheblich. Listing 3 zeigt, wie der FXGraph für das FXML-Dokument, wie in Abbildung 3 dargestellt, geschrieben werden könnte. Die DSL lässt sich sehr leicht lesen. Auf den ersten Blick ist erkennbar, welcher externe Controller verwendet wird und in welcher Datei sich das CSS-Styling befindet. Zum Aufbau der Oberfläche verwendet FXGraph eine hierarchische Struktur: Die Scene enthält das GridPane, auf dem GridPane liegen dann Label und die beiden Buttons. Die Eigenschaften und Attribute werden durch Kommata getrennt, der FXGraph-Editor unterstützt beim Schreiben an nahezu jeder Stelle mit Codevervollständigung.

Listing 3
package net.teufel.javafx

import javafx.scene.Scene
import javafx.scene.layout.GridPane
import net.teufel.javafx.HelloWorldFxGraphController
import javafx.geometry.Insets
import javafx.scene.control.Label
import javafx.scene.control.Button

component HelloWorldFXGraph controlledby HelloWorldFxGraphController styledwith "design.css" {
Scene {
GridPane {
alignment : "CENTER",
hgap : 1, vgap : 1,
padding : Insets {
top : 10, right : 10, left : 10, bottom : 10
},
Label id labelTitel {
text : "Hello World",
static columnIndex : 0, static rowIndex : 0
},
Button id buttonDatum {
text : "Datum",
static columnIndex : 0, static rowIndex : 1,
onAction : controllermethod datumAnzeigen
},
Button id buttonZeit {
text : "Zeit",
static columnIndex : 0, static rowIndex : 2,
onAction : controllermethod zeitAnzeigen
}
}
}
}

Mittlerweile sind FXML- und FXGraph-Editor von der Funktionalität her gleichauf, sodass es letztendlich reine Geschmackssache ist, ob man JavaFX-Oberflächen direkt in FXML schreibt oder den Weg über einen FXGraphen bevorzugt. In jedem Fall ist die FXGraph-DSL im Vergleich zu FXML sehr viel einfacher zu lesen und schreiben, sie wirkt wie ein Fluent Interface. Im Moment ist e(fx)clipse nur in der Lage, aus einem FXGraphen eine FXML-Darstellung zu generieren. In zukünftigen Versionen soll hier ein vollständiger Zyklus angeboten werden, sodass aus einem FXML-Dokument auch ein FXGraph generiert werden kann. Dies ist dann wichtig, wenn man zwischendurch Veränderungen mit dem SceneBuilder (der nur auf Basis von FXML arbeitet) durführen will, danach aber wieder im FXGraphen arbeiten möchte. Da sich die FXGraph-Sprache von Xbase ableitet, wird es in Zukunft vielleicht auch möglich sein, einfache Expressions in FXGraph zu schreiben.

Fazit

Mit e(fx)clipse gibt es nun auch vernünftiges JavaFX Tooling für Eclipse. Für nahezu alle Bereiche bietet das Werkzeug dabei Unterstützung an: Wizards erleichtern das Anlegen von JavaFX-Projekten oder einzelner Artefakte. e(fx)clipse integriert JavaFX in JDT, sodass die Entwicklung von JavaFX-Anwendungen genauso angenehm möglich wird wie das Schreiben von Swing- oder SWT-Anwendungen. Die Verbindung des integrierten FXML-Editors mit der JavaFX Live Preview ist eine hervorragende Kombination, wenn es darum geht, deklarative Oberflächen zu bauen. Auch das Schreiben von CSS geht mit dem CSS-Editor leicht von der Hand. Zu den eher fortgeschrittenen Möglichkeiten gehört sicherlich FXGraph, das eine DSL zum Schreiben von JavaFX-Oberflächen anbietet, an dessen Ende jedoch immer FXML steht. Die Vorteile von FXGraph sind dabei der gute, tief mit JDT verwurzelte Editor und die leicht lesbare und erlernbare Syntax. Außerdem ist e(fx)clipse jederzeit in der Lage, einen FXGraphen zu parsen und in der Live Preview darzustellen. Schlussendlich bekommen die Entwickler im Rahmen von e(fx)clipse einen speziellen Renderer für die Eclipse 4 Application Platform geliefert, mit dem es möglich wird, Eclipse-4-Anwendungen auf Basis von JavaFX zu schreiben. Zum Erstellen solcher Eclipse-4-Anwendungen hält e(fx)clipse einen eigenen Wizard bereit, mit dem sich Beispielanwendungen und Grundgerüste generieren lassen. Die meisten Aspekte rund um das Werkzeug sind auf seiner Webseite [1] sehr gut dokumentiert. Auch finden sich dort viele interessante Tutorials. Obwohl e(fx)clipse aktuell noch nicht in einer 1.x-Version vorliegt, hat es schon heute einen erstaunlichen Reifegrad erreicht.

Geschrieben von
Marc Teufel
Marc Teufel
Marc Teufel arbeitet als Projektleiter und Softwarearchitekt bei der hama GmbH & Co KG und ist dort für die Durchführung von Softwareprojekten im Bereich internationale Logistik zuständig. Er ist Autor zahlreicher Fachartikel im Web-Services- und Eclipse-Umfeld. Er hat drei Bücher zu Web Services veröffentlicht, sein aktuelles Buch „Eclipse 4 – Rich Clients mit dem Eclipse 4.2 SDK“ ist kürzlich bei entwickler.press erschienen.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.