30.07.2013

Tipps & Tricks – JavaFX und Eclipse 4

JavaFX bietet Entwicklern viele neue Möglichkeiten, elegante und graphisch ansprechende User Interfaces zu implementieren. Insbesondere bietet JavaFX die Möglichkeit, das Layout von GUIs auch auf der Basis des XML-basierten FXML Formats zu definieren und so auf umfangreiche und unübersichtliche Layout Blöcke im Java Code weitgehend zu verzichten.

Ein sehr gutes Tutorial zu JavaFX findet sich z.B. auf den Seiten von Oracle: Getting Started with JavaFX — Alle Codebeispiele unten basieren auf Code aus diesem Tutorial.

Eine wesentliche Neuerung in Eclipse Version 4 ist das Application Model, das eine Integration verschiedener, voreinander unabhängiger Views auf der Basis eines XMI-basierten high-level Models erlaubt.

Damit liegt es natürlich nahe, in eine Eclipse RCP Anwendung auch Views, die mit FXML implementiert sind, zu integrieren, indem man sie einfach in das Application Model einklinkt.

Da aber Eclipse RCP auf dem OSGi Framework mit seinem eigenen Classloading Konzept basiert, funktionieren die FXML Beispiel Anwendungen aus dem Tutorial unter Eclipse nicht Out-of-the-Box, sondern müssen an den entscheidenden Stellen angepasst werden.

So wird im JavaFX Tutorial folgender Code zum Laden der FXML Datei verwendet:

Example 4-1 FXMLExample.java

@Override
public void start(Stage stage) throws Exception {

Parent root =
FXMLLoader.load(getClass().getResource("fxml_example.fxml"));

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

stage.setTitle("FXML Welcome");
stage.setScene(scene);
stage.show();
}

Unter Eclipse 4 erfolgt Laden der FXML Datei dagegen in der Initialisierung des entsprechenden View Parts in der Methode, die mit der Annotation @PostConstruct ausgezeichnet ist. Der Code kann dann z.B. so aussehen:

package application.parts;

import java.io.IOException;

import javafx.scene.Node;
import javafx.scene.layout.BorderPane;

import javax.annotation.PostConstruct;
import javax.inject.Inject;

import org.eclipse.e4.ui.di.Focus;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;

import at.bestsolution.efxclipse.runtime.di.InjectingFXMLLoader;

public class LoginPart {

@Inject
MPart part;

private Node focusNode;

@PostConstruct
void init(BorderPane p) {
InjectingFXMLLoader<Object> fxmlLoader =
InjectingFXMLLoader.create(part.getContext(),
getClass(), "LoginPart.fxml");

// Using FXMLLoader in eclipse/OSGi context yields:
// java.lang.ClassNotFoundException:
// application.parts.LoginController
// FXMLLoader fxmlLoader =
// new FXMLLoader(getClass().getResource("LoginPart.fxml"));

Node node = null;

try {
node = (Node) fxmlLoader.load();

if(node != null) {
p.setCenter(node);
focusNode = node;
}
} catch (IOException exception) {
exception.printStackTrace();
}
}

@Focus
void focus() {
if( focusNode != null ) {
focusNode.requestFocus();
}
}
}

Das Laden der FXML Datei übernimmt dabei die Klasse InjectingFXMLLoader aus dem efxclipse Plugin von BestSolution.at. Dieses Plugin leistet die eigentliche Integration von JavaFX/FXML in die OSGi und Eclipse 4 Welt und wird in allen folgenden Codebeispielen als Implementierungsbasis genutzt.