Wie verwendet man ein GridPane
?
Der Ausgangszustand
Als Ausgangsbasis erzeugen wir eine einfache recht sinnfreie
Anwendung mit einem Textbereich, einem Label und einem Button.
Das gesamte Fenster besteht aus zwei Zeilen und zwei Spalten
zunächst ohne weitere Konfiguration, von denen je zwei
neben- und übereinander angeordnet sind. Der Textbereich
befindet sich links oben, das Label links unten und der Button
rechts unten. Die genannten Kindknoten werden hier durch die
Methode add()
unter Angabe der Spalten- und
Zeilenindices direkt dem GridPane
hinzugefügt.
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.GridPane; import javafx.scene.text.Text; import javafx.stage.Stage; public class GridLayoutBsp extends Application { @Override public void start(Stage primaryStage) throws Exception { Label label = new Label("Label"); Text text = new Text(0,0,"Ene mene Maus und Du bist raus!"); Button button = new Button("klick"); GridPane grid = new GridPane(); grid.add(text, 0, 0); grid.add(label, 0, 1); grid.add(button, 1, 1); Scene scene = new Scene(grid); primaryStage.setScene(scene); primaryStage.setTitle("GridPane Beispiel"); primaryStage.show(); } public static void main(String[] args) { launch(); } }
Das Hinzufügen der Knoten zum GridPane
kann
auf verschiedene Weisen erfolgen. So wäre statt der oben
angeführten Zeile zum Setzen des Label
-Objektes
auch folgende Version möglich, bei der nach Setzen der
Spalten- und Zeilenidices das Label
der ObservableList
aller Knoten des GridPane
hinzugefügt wird:
GridPane.setRowIndex(label, 1); GridPane.setColumnIndex(label, 0); grid.getChildren().add(label);
Bei der Erscheinung des erzeugten Anwendungsfensters fällt zunächst auf, dass alle Elemente so gerade in ihre Zellen passen, deren Größe sich also nach der bevorzugten Größe der GUI-Elemente richtet und der Inhalt jeweils linksbündig ausgerichtet ist. Der Textbereich mit dem Abzählreim besetzt tatsächlich nur die Zelle links oben, expandiert diese jedoch nach Platzbedarf.
Wird der Text durch \n
folgendermaßen
umgebrochen,
Text text = new Text("Ene mene Maus\nund Du bist raus!");
so ändert sich die Textanordnung im Text
-Knoten
und mit diesem auch die Größe des gesamten Fensters,
ohne dass zusätzliche Angaben nötig wären.
Man kann dies gut verdeutlichen, indem man durch
grid.setGridLinesVisible(true);
die Anzeige der Rasterlinien aktiviert. Es ist zu erkennen, dass
sich Breite und Höhe der Zellen nach dem Platzbedarf des in
der jeweiligen Spalte und Zeile befindlichen GUI-Elementes
richtet. Hieraus resultieren unterschiedliche
Zellengrößen - ein wesentlicher Unterschied etwa zum GridLayout
in Swing.
Vergrößert man das Fenster durch Ziehen mit der Maus,
so bleibt das gesamte GridPane
links oben verankert
und seine Elemente wachsen in der Standardeinstellung nicht mit.
Ein Verschmelzen von Zellen kann durch die statische Methoden GridPane#setColumnSpan()
bzw. GridPane#setRowSpan()
erreicht werden. Hierzu
muss der zu erweiternde Knoten, sowie die Anzahl der Zellen, die
verbunden werden sollen als Parameter übergeben werden.
Das
Ausführen von
GridPane.setColumnSpan(text, 2);
im Beispiel erzeugt nach leichtem Vergrößern des Fensters mit der Maus die folgende Erscheinung
Aus den Linienverläufen des Rasters kann man entnehmen, dass beim Überspannen kein wirkliches Verschmelzen der Rasterzellen stattfindet, sondern lediglich eine Erweiterung des Zelleninhalts erfolgt.
Erweitert man dies insofern, dass zusätzlich noch zwei Zeilen überspannt werden durch
GridPane.setRowSpan(text, 2);
so ergibt sich das folgende hier unbrauchbare Fenster.
Die Schichtungsreihenfolge resultiert hierbei aus der
Reihenfolge des Hinzufügens der GUI-Knoten zum GridPane
.
Positionierung von Zelleninhalten
Die beiden statischen Methoden GridPane#setHalignment()
und GridPane#setValignment()
steuern die
Ausrichtung der Kindelemente im Raster. Eine Angabe von
GridPane.setHalignment(label, HPos.RIGHT);
führt bezüglich des Labels zu folgendem Aussehen
Als erster Parameter wird der betroffene Kindknoten angegeben, als zweiter Parameter stehen hier die folgenden selbsterklärenden Angaben zur Verfügung:
HPos.LEFT
HPos.RIGHT
HPos.CENTER
Für die vertikale Ausrichtung durch setValignment()
stehen analog die folgenden Enum
-Konstanten zur
Verfügung:
VPos.BASELINE
VPos.BOTTOM
VPos.CENTER
VPos.TOP
Die Vergrößerung oder Verkleinerung von Zellen in
vertikale und horizontale Richtung beim Aufziehen des Fensters
kann durch die statischen Methoden GridPane#setVgrow()
und GridPane#setHgrow()
gesteuert werden. Der in
Ergänzung zum Knoten als zweiter zu übergebene
Parameter ist hier vom Enum-Typ Priority
. Sein
Einfluss wird in der folgenden Tabelle dargestellt.
GridPane.setHgrow(label, Priority.ALWAYS); |
|
GridPane.setHgrow(label, Priority.ALWAYS); |
|
GridPane.setHgrow(label, Priority.SOMETIMES); |
|
GridPane.setHgrow(label, Priority.NEVER); |
Beim ersten und dritten Beispiel ist zu erkennen, dass die
Zellen mit Label
und mit Button
beim
Aufziehen des Fensters in gleichem Maße wachsen. Man
beachte, dass das Label
-Feld im Ausgangszustand,
bedingt durch die darüber angeordnete Text
-Komponente,
bereits einen größeren Platz beansprucht. Der Zuwachs
ist in beiden Zellen identisch.
Zellen-, Zeilen- und Spaltenformatierung durch Constraints
Möchte man die Formatierung von Zellen gezielt beeinflussen, so kann dies für den einzelnen Kindknoten oder zeilen- bzw. spaltenweise erfolgen.
Zeilen- und spaltenweise Zuweisung von Constraints
Die Klassen RowConstraints
und ColumnConstraints
stellen Werkzeuge zur zeilen- und spaltenweisen Formatierung zur
Verfügung. Ihre Konstruktoren sind jeweils vierfach
überladen und nehmen bei der Bildung entweder keinen,
einen, drei oder sechs Parameter entgegen. Am Beispiel von RowConstraints
soll der Umgang hiermit beispielhaft demonstriert werden. Die
Deklaration von ColumnConstraints
erfolgt analog.
RowConstraints rc = new RowConstraints( 100, // minimale Höhe 100, // bevorzugte Höhe 100, // maximale Höhe Priority.ALWAYS, // vertikale Ausdehnung VPos.BOTTOM, // vertikale Anordnung true); // vertikale Füllung
Constraints können auf unterschiedliche Art und Weise an
ein GridPane
übergeben werden. Eine Methode
besteht darin, sich die ObservableList
aller RowConstraints
des GridPane
mit getRowConstraints()
zu holen und dieser die deklarierten Constraints
hinzuzufügen.
grid.getRowConstraints().add(rc);
Die o.a. Constraints führen zur folgenden Ausgabe.
Wird nur eine RowConstraints
-Angabe gemacht, so
bezieht sich diese auf die erste Zeile von oben. Für jede
Zeile können gesonderte Constraints angegeben werden, die
mit Hilfe der Methode addAll()
gemeinsam dem GridPane
hinzugefügt werden
können. Die Methode addAll()
kann eine
variable Parameterzahl entgegennehmen, die von oben nach unten
die einzelnen Zeilen formatieren.
RowConstraints rc1 = new RowConstraints(100, 100, 100, Priority.ALWAYS, VPos.BOTTOM, true); RowConstraints rc2 = new RowConstraints(50, 50, 50, Priority.SOMETIMES, VPos.CENTER, true); grid.getRowConstraints().addAll(rc1, rc2);
Eine wahlfreie Ansprache einzelner Zeilen ist hierbei jedoch
nicht möglich. Soll eine Zeile nicht von der
Standarddarstellung abweichend formatiert werden, so muss bei
diesem Vorgehen ein leeres RowConstraints
-Objekt
übergeben werden.
Constraints für einzelne Knoten
Eine zweite auch hinsichtlich der
Formatierungsmöglichkeiten etwas abweichende Vorgehensweise
bei der Übergabe von Constraints an ein GridPane
besteht durch die fünffach überladene statische
Methode GridPane#setConstraints()
. Hiermit ist auch
die wahlfreie Ansprache einzelner Kindknoten möglich. Einen
Überblick über die Methodenversionen gibt die folgende
Auflistung:
setConstraints(Node child, int columnIndex, int
rowIndex) |
setConstraints(Node child, int columnIndex, int
rowIndex, int columnspan, int rowspan) |
setConstraints(Node child, int columnIndex, int
rowIndex, int columnspan, int rowspan, HPos
halignment, VPos valignment) |
setConstraints(Node child, int columnIndex, int
rowIndex, int columnspan, int rowspan, HPos
halignment, VPos valignment, Priority hgrow,
Priority vgrow) |
setConstraints(Node child, int columnIndex, int
rowIndex, int columnspan, int rowspan, HPos
halignment, VPos valignment, Priority hgrow,
Priority vgrow, Insets margin) |
Ein Aufruf der letzten Methodenversion mit zehn Parametern
GridPane.setConstraints( text, // Knotenelement 0, // Spaltenindex 0, // Zeilenindex 2, // Anzahl überspannter Spalten 1, // Anuahl überspannter Zeilen HPos.CENTER, // horizonale Anordnung VPos.BOTTOM, // vertikale Anordnung Priority.ALWAYS, // horizontale Ausdehnung Priority.ALWAYS, // vertikale Ausdehnung new Insets(20) // Abstand des Inhaltes zum Zellenrand );
führt nach Vergrößerung des Fensters zu der folgenden Ansicht
Es ist erkennbar, dass auf diese Weise die Ansprache eines
ausgewählten Knotens, hier des Text
-Objektes,
und damit einer bestimmten Zelle eines GridPane
möglich ist.
Allerdings haben die Formatierungen einzelner Zellen wiederum
Auswirkungen auf diejenigen anderer Zellen. Hier ist
auffällig, dass trotz der Angabe von Priority.ALWAYS
für die horizontale Ausdehnung der Text
-Zelle
diese auf die Ausgangsbreite fixiert ist und nicht horizontal
expandiert werden kann. Die Ursache ist in der unteren Zeile zu
suchen, deren Elemente keine Ausdehnung zulassen. Erlaubt man
die Ausdehnung des Label
-, des Button
-Objektes
oder beider z.B. durch Vergabe von Priority.ALWAYS
,
so ist auch eine horizontale Expansion möglich.
Die zur obigen Angabe zusätzliche Ausdehnung des Button
-Objektes
durch
GridPane.setHgrow(button, Priority.SOMETIMES);
führt zur folgenden Ausgabe:
Diejenige des Label
-Objektes zu dieser:
Hier zeigt sich im Vergleich, dass zusätzlich zum
Expansionsverhalten auch die Position des Abzählreims im Text
-Objekt
durch diese Angabe beeinflusst wird.
Ausführliches
Testen eines gewünschten Layouts ist somit in jedem Falle
angeraten.
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.