Die Klasse HelloWorldApplication
implementiert die Schnittstelle IApplication
.
Diese hat eine Startmethode, welche den
Lifecycle
als Parameter liefert. Wird auf
diesem die Methode finish()
aufgerufen, wird
die Applikation beendet.
Will man jowidgets in nativen Ui Code (z.B. Swing oder SWT) integrieren, hat man in der Regel keine IApplication zum starten. Stattdessen werden das Root Fenster (z.B. Shell oder JFrame) und weitere Widgets (z.B. Composite, JPanel) nativ erzeugt. In Jowidgets Code in native Projekte integrieren wird erläutert, wie man in diesem Fall vorgehen kann.
1 package org.jowidgets.helloworld.common; 2 3 import org.jowidgets.api.toolkit.Toolkit; 4 import org.jowidgets.api.widgets.IButton; 5 import org.jowidgets.api.widgets.IFrame; 6 import org.jowidgets.api.widgets.blueprint.IButtonBluePrint; 7 import org.jowidgets.api.widgets.blueprint.IFrameBluePrint; 8 import org.jowidgets.common.application.IApplication; 9 import org.jowidgets.common.application.IApplicationLifecycle; 10 import org.jowidgets.common.types.Dimension; 11 import org.jowidgets.common.widgets.controller.IActionListener; 12 import org.jowidgets.common.widgets.layout.MigLayoutDescriptor; 13 import org.jowidgets.tools.widgets.blueprint.BPF; 14 15 public final class HelloWorldApplication implements IApplication { 16 17 @Override 18 public void start(final IApplicationLifecycle lifecycle) { 19 20 //Create a frame BluePrint with help of the BluePrintFactory (BPF) 21 final IFrameBluePrint frameBp = BPF.frame(); 22 frameBp.setSize(new Dimension(400, 300)).setTitle("Hello World"); 23 24 //Create a frame with help of the Toolkit and BluePrint. 25 //This convenience method finishes the ApplicationLifecycle when 26 //the root frame will be closed. 27 final IFrame frame = Toolkit.createRootFrame(frameBp, lifecycle); 28 29 //Use a simple MigLayout with one column and one row 30 frame.setLayout(new MigLayoutDescriptor("[]", "[]")); 31 32 //Create a button BluePrint with help of the BluePrintFactory (BPF) 33 final IButtonBluePrint buttonBp = BPF.button().setText("Hello World"); 34 35 //Add the button defined by the BluePrint to the frame 36 final IButton button = frame.add(buttonBp); 37 38 //Add an ActionListener to the button 39 button.addActionListener(new IActionListener() { 40 @Override 41 public void actionPerformed() { 42 System.out.println("Hello World"); 43 } 44 }); 45 46 //set the root frame visible 47 frame.setVisible(true); 48 } 49 }
Im Vergleich zu anderern UI Frameworks gibt es in jowidgets
einen wesentlichen Unterschied bei der Widget Erzeugung. Widgets
werden nicht direkt, also mit Hilfe des new
Schlüßelwortes instantiiert, sondern von einer Factory erzeugt.
Dies hat einige Vorteile, siehe dazu auch
Die Generic Widget
Factory.
Die Wigdet Factory benötigt für die Erzeugung eines Widgets ein
sogenanntes BluePrint (Blaupause). Siehe
dazu auch BluePrints.
BluePrints erhält man von der
BluePrint Factory. Die
Klasse
BPF
liefert einen Zugriffspunkt auf alle BluePrints der BluePrint
Factory. In Zeile 21 wird so das BluePrint für ein Frame und in
Zeile 33 das BluePrint für einen Button erzeugt. BluePrints sind
Setup und
Builder zugleich.
Sie werden dazu verwendet, das Widgets zu Konfigurieren und
liefern dadurch der Implementierung das initiale Setup des
Widgets. In Zeile 22 wird so die Größe und der Titel des
Fensters gesetzt. In Zeile 33 wird so das Button Label
definiert. BluePrints sind nach dem Prinzip des
BuilderPattern entworfen, das heißt sie
liefern die eigene Instanz als Rückgabewert, um verkettete
Aufrufe zu ermöglichen.
In der Regel wird die
Generic Widget
Factory nicht explizit verwendet. Um das root Fenster zu
erhalten, wird in Zeile 27 ein IFrame Widget mit Hilfe des
frameBp
und des
Toolkit’s
erzeugt. Bei der verwendeten Methode handelt es sich um eine
convenience Methode die beim Schließen des
Fensters den ApplicationLifecycle
beendet.
Das Frame ist gleichzeitig auch ein Container. Um ein Widget zu
einem Container hinzuzufügen, fügt man das BluePrint hinzu und
erhält dafür das Widget. In Zeile 36 wird so der Button erzeugt.
In Zeile 30 wird das Layout mit einer Spalte und einer Zeile für das Frame gesetzt. Zeile 39 fügt dem erzeugten Button einen Listener hinzu, welcher beim Klicken eine Konsolenausgabe macht. In Zeile 47 wird das Fenster schlußendlich angezeigt.
Um Widgets zu erhalten, benötigt man vorab ein BluePrint. Dieses erhält man von der BluePrint Factory. Auf dem BluePrint kann man das Setup konfigurieren. Für ein BluePrint bekommt man dann ein Widget.
Auch wenn sich das vielleicht erst mal ungewohnt anhört, ist das auch schon alles, was im Vergleich zu anderen UI Frameworks generell anders ist.
Man wird zudem schnell feststellen, dass man dadurch sehr kompakten und zudem gut lesbaren UI Code erzeugen kann. Den im Vergleich zu langen Konstruktoraufrufen ist beim Builder Pattern immer klar, welchen Parameter man konfiguriert. Außerdem kann die Erzeugung von BluePrints meist auch implizit passieren. So könnte man den Code von Zeile 32 bis 36 auch so aufschreiben:
final IButton button = frame.add(BPF.button().setText("Hello World"));
Zudem können BluePrints für die Erzeugung mehrerer Instanzen wiederverwendet werden, was sich oft als sehr hilfreich erweißt.
Anbei folgen noch ein paar Anmerkungen zum Code Style:
Unter dem Begriff CleanCode findet sich der Hinweis, immer sprechende Variablennamen zu verwenden, und insbesondere kryptische Variablennamen wie: „is, os, hfu, jkl, …“ etc. zu vermeiden. Im Allgemeinen ist dem auch voll zuzustimmen.
Da jedoch BluePrints in jowidgets eine so fundamentale Rolle
spielen, wird hier dennoch bewusst von dieser Regel abgewichen.
Der Name der Abbreviation Accessor Klasse
BPF
wurde bewußt kurz gewählt, um eine
bessere inline Verwendung (siehe oben) zu
ermöglichen. (Wer das trotzdem nicht mag, kann anstatt
BPF.button()
auch
Toolkit.getBluePrintFactory().button()
schreiben.)
Um BluePrint Variablen besser von den eigentlichen Widget
Variablen unterscheiden zu können, sollten diese per Konvention
immer die Endung bp
oder
bluePrint
haben. Wird das BluePrint nur für
die Erzeugung eines einzelnen Widgets verwendet, bietet es sich
an, für BluePrint und Widget den gleichen Präfix zu wählen, also
zum Beispiel buttonBp
und
button
.