Eine Benutzeroberfläche mit FXML erstellen – Einleitung JavaFX

JavaFx und FXML

Was ist schon ein Programm ohne eine schöne Benutzeroberfläche? Natürlich ist das Wichtigste, dass ein Programm das tut was es soll, aber wenn es das mit einer ansprechenden Oberfläche macht ist das doch noch viel schöner. Die modernste und einfachste Möglichkeit eine GUI in Java zu bauen besteht darin eine Benutzeroberfläche mit FXML zu erstellen. Schauen wir mal wie das geht…

Bevor wir anfangen können zu Programmieren müssen wir erst einmal dafür sorgen das wir überhaupt JavaFX Anwendungen erstellen können. Seitdem JavaFX kein Bestandteil mehr vom JDK ist, gestaltet sich das leider nicht mehr ganz so einfach. Wir müssen es also separat hinzufügen und die nötigen Konfiguationen in der IDE machen. Am besten suchst du dir einfach den für dich besten Weg von der offiziellen Website, https://openjfx.io/openjfx-docs/. Dort ist alles genau erklärt für die IDE die du verwendest und abhängig davon ob du Maven verwenden möchtest oder nicht. Solltest du trotzdem noch Fragen haben lass doch einen Kommentar da.

Lass uns anfangen – Erstes Projekt

Wenn du der Anleitung auf der Seite gefolgt bist dürftest du inzwischen schon ein lauffähiges FX-Projekt haben, wir können also sofort los legen. Ich möchte dir noch nahelegen den SceneBuilder zu installieren. Der SceneBuilder erleichtert dir die Arbeit massiv, den mit ihm kannst du im schnellverfahren durch Drag and Drop eine schöne Benutzeroberfläche mit FXML zusammenstellen. Er generiert dir dann mit jedem speichern den entsprechenden FXML Quellcode dazu.

SceneBuilder einrichten

  1. SceneBuilder von Gluon runterladen und installierren

    Du kannst ganz einfach den für deine Java-Version passenden SceneBuilder von der Website von Gluon runterladen und im Anschluss wie jedes andere Programm installieren.

  2. Finde in deiner IDE den SceneBuilder Path


    Hier kannst du sehen wo du ihn bei IntelliJ findest. Im Normalfall sollte sich der Path irgendwo in der Nähe zu den Language/Java Einstellungen befinden.

  3. Suche den Pfad zu deinem SceneBuilder

    Entweder hat du dir im Vorfeld schon den Pfad zu deiner SceneBuider Installation kopiert oer ddu klickst dich kurz durch den Explorer. Wenn du bei der Installation keinen speziellen Pfad angegeben hast sollte es im Ordner „Program Files“ installiert sein.

Aufbau eines FX-Projekt

Jedes frisch erstellte JavaFX-Projekt besteht aus einer Main-Klasse in der schon ein Fenster erstellt wurde, einem Controller und einer sample.fxml. Die Grundlage einer jeden Benutzeroberfläche mit JavaFX bildet die Stage, also…

Bauen wir die Stage auf.

Ein ganz einfaches Fenster nennt sich Stage. Eine Stage aufzubauen ist gar nicht so schwer. In der Regel hat ein Programm eine Main-Stage und eventuell noch kurzzeitig mehrere kleinere Stages (Stichwort Pop-Ups). Jede Stage hat eine Scene. Die Scene sammelt im wesentlichen alle grafischen Merkmale. Sie lädt auch mit Hilfe eines FXMLLoaders unsere FXML Datei und holt sich von dort alles was sie wissen muss. Wenn du später ein Paging realisieren möchtest, musst du also nicht viel mehr machen als die Scene wechseln. Klingt easy oder?

All das was ich gerade beschrieben habe, wird bei einem autogenerierten Programm automatisch gemacht, nichts desto trotz solltest du wissen was dort passiert, da es hier häufig zu Fehlern kommt.

Das ganze sieht in Programm-Code wie folgt aus:

@Override
    public void start(Stage primaryStage){
        FXMLLoader loader = new FXMLLoader(getClass().getResource("sample.fxml")); // Hier wird mit Hilfe des FXMLLoaders unsere GUI geladen.. 
        Parent root = loader.load(); 
        this.c = loader.getController(); //Jede GUI benötigt einen Controller, also jemand der weiß was die einzelnen Elemente können (weiter unten gehe ich darauf noch genauer ein)
        primaryStage.setTitle("Title");
        primaryStage.setScene(new Scene(root)); //Hier übergibst du deiner Stage eine Scene, du kannst auch vorher mehrere Scens erstellen, die dann nur noch gesetzt werden müssen
        primaryStage.show(); // Das ist die Zeile die dafür sorgt das dein Fenster dir auch angezeigt wird

Das ist der wesentliche Aufbau eines einfachen Projektes. Der FXMLLoader kann auch direkt in der Scene nur die FXML laden ohne initialisiert zu werden. Du musst dann den Controller direkt in der FXML Datei übergeben. Dafür musst du einfach auf dein erstes Element gehn und in dort mit dem Befehlt: fx:controller=“Controllerklasse.java“ dein Controller definieren. Leider kann das zu Problemen führen wenn man mehrere FXML Benutzeroberflächen mit verschiedenen Controllern ineinander verschachtelt. Deshalb setze ich den Controller lieber auf diese Weise.

InvocationTargetException

Solltest du einmal eine ewig Lage Fehlermeldung bekommen, in der irgendetwas von „InvocationTarget“ steht und die Meldung verweist auf deinen FXMLLoader, dann brauchst du nicht erschrecken. Dieser Fahler heißt nicht viel mehr al das der Loader deine FXML nicht laden kann. Dafür gibt es ganz ssimple Gründe, du könntest den Pfad nciht korrekt angegeben haben. Wenn der Pfad stimmt gibt es häufig einen Fehler in der FXML. Du solltest dann also unbedingt mal in den Quellccode gucken um zu sehen ob dir dort ein Fehler angezeigt wird den du beheben musst. Solltest du dann den Fehler nicht finden könen wir gerne zusammen noch einmal gucken wo der Fehler liegt, schreib einfach mal ein Kommi.

Die FXML-Benutzeroberfläche – die sample.fxml

Um ein möglich sauberes, gut lesbares und wartbares Programm zu erhalten hat es oberste Priorität das Frontend(der grafische Teil der Benutzeroberfläche, die FXML) von dem Backend(allen Funktionen) zu trennen. In der sample Datei sind alle Optischen Merkmale deiner Benutzeroberfläche enthalten. Wenn du also deine sample.fxml veränderst ändert sich das Aussehen deiner Benutzeroberfläche.

Die sample Datei bildet deine komplette Benutzeroberfläche, also alles was du siehst wenn du das Programm startest. So sieht der Quellcode einer FXML Benutzeroberfläche aus, nachdem sie gerade erstellt wurde:

Eine initial Erstellte sample.fxml

Bearbeiten der FXML mit dem SceneBuilder

An der Stelle kommt der SceneBuilder wieder ins Spiel, mit ihm kannst du ganz entspannt dein User Interface (UI) zusammen klicken.

Du öffnest ihn indem du einen Rechtsklick auf die sample machst und dann „Open in SceneBuilder“ auswählst.

Ich empfehle immer bei einem neuen Projekt das schon vorhandene GridPane zu löschen und mit dem eigenen Wunsch-Panel zu ersetzen. Dafür musst du unter „Hierachy“ auf der linken Seite das Element löschen. Du löschst es entweder mit auswählen und entfernen auf der Tastatur drücken oder indem du mit der rechten Maustate drauf klickst und „Delete“ auswählst.

Über Hierarchy hast du dann eine Auswahl an Elementen mit denen du deine GUI bestücken kannst. Der FXML Quellcode zur Benutzeroberfläche dazu wwird beim speichern autmatisch geeriert. Ein Element kann entweder per Doppelklick oder durch auf das Feld ziehen platziert werden.

Im Anschlusss kannst du das gerade ausgewählten Element in der rechten Spalte anpassen.

Jedes Element das du späterr verwenden möchtest benötigt eine ID. Die ID stellst du rechts unter „Code“ ein.

Alternativ kannst du auch immer den Namen selber in der FXML eintragen.

Nahdem wir unser Label hinzugefügt und gespeichert haben sieht der FXML Code der Benutzeroberfläche wie folgt aus:

Um die Änderungen auch im ullcode sichtbar zu mchen ist es notwendig vorher die atei zu speichern. Du kannst natürlich auch immernoch elber Anpassungen in der FXML vornehmen, du musst nur immer aufpassen damit keine Versionskoflikte zu erzeugen. Also immer daarauf achten zu speichern und die Dateien zu aktualisieren.

Der Controller

Da wir aber auch von irgendwo unsere Daten brauchen benötigen wir den Controller. Ein Controller ist die Schnittstelle zwischen Frontend und Backend. Wenn also irgendein Element auf der Oberfläche etwas machen soll wird über den Controller die entsprechende Funktion aufgerufen. Umgekehrt geht das natürlich auch, wenn also eine Funkion aus dem Backend Daten aus dem Frontend benötigt muss er den Controller ansprechen um an diese Daten zu kommen. Ausschließlich der Controller kommuniziert mit dem Frontend. Jede FXML Datei ist dabei mit genau einem Controller verknüpft, wobei natürlich auch zwei FXML Dateien mit dem selben Controller verknüpft sein könnten.

Du findest die Verknüpfung ganz oben, bei dem ersten Panel deiner UI. Der Befehl: ‚ fx:controller =“sample.Controller“ ‚ zeigt dir das in diesem Fall die Klasse „Controller“ aus dem sample-Package der dazugehörige Controller ist.

Das Verknüpfen der Elemente mit dem Controller nennt sich „Data Binding“ und das ist in Java sehr einfach und schnell erklärt.

Alles was du im Controller machst und das direkten Einfluss auf die FXML haben soll wird einfach mit der Annotation „@FXML “ darüber gekennzeichnet und verwendest den selben Namen wie bei der fx:id. Möchtest du also ein Element wie unser Label ansprechen sieht das wie folgt aus:

@FXML
private Label Lbl_Title;

Von nun an kannst du das Element auch in deinem Quellcode unter diesem Namen aufrufen.

Sollte dads Element einmal nicht erkannt werden, obwohl der Name und Objekttyp identisch sind solltest du deine Importe kontrollieren. Es kann ziemlicch schnell passieren, dass bei einem Auto-Import ein falsches Element zwischenrutscht. Du musst also darauf achten das alle Importe aus dem JavaFX package sind.

Der Eventhandler

Möchtest du in JavaFX einem Element eine Funktion zuweisen machst du das über ein Event. Wenn ein bestimmtes Event eintritt ruft der Eventhandler die entsprechende Funktion auf. Ein Event kann ein Mausklick sein oder die Eingabe von Enter, oder, oder, oder… . Dafür stehen einem glücklicherweise verschiedene Eventtypen zur Verfügung.

Gucken wir uns mal ein Beispiel an.

@FXML
public void setLableText(){
  Lbl_Title.setText("neuer Label-Text");
}

Sieht aus wie eine ganz normale Funktion? Ist es auch. Unsere Anwendung kann auch immernoch nicht mehr als vorher, das kommt jetzt.

Ich habe jetzt noch einen Button namens „Btn_setTitle“ auf der Beutzeroberfläche platziert und mit dem Controller verknüpft:

public class Controller {

    @FXML
    private Label Lbl_Title;
    @FXML
    private Button Btn_setTitle;

    @FXML
    public void setLableText(){
        Lbl_Title.setText("neuer Label-Text");
    }
}

Jetzt müssen wir dem Button nur noch die Funktion zuweisen. Dafür gehst du auf den SceneBuilder, wählst den Button aus und gehst in der rechten Spalte auf Code. Dort definierst du bei welchem Event was passieren soll. Wir schreiben in das Feld „On Action“ den Namen unserer Methode. Immerhin ist uns nicht wichtig ob man mit der Maus drauf klickt oder mit der Tastaur das Feld auswählt.

Lass uns die Anwendung starten und gucken was passiert.

So sieht es aus, wenn alles funktioniert.

Wenn dir der Beitrag gefallenn hat, lass doch ein Like oder Kommi da. 🙂 Bis nächsten Mittwoch 🙂

Einen Kommentar hinzufügen

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