Literatur

GridLayout

Auch das GridLayout ist ein Manager, der Ihnen die Gestaltung Ihrer Oberfläche völlig völlig aus der Hand nimmt. Es ordnet die Elemente in einem Zeilen-/Spalten-Raster an, und geht dabei ausgesprochen stur vor. Einzig die Anzahl von Zeilen und Spalten gibt man an, (fast) alles andere erledigt das Grid. „Fast“, weil man eine einzige Gestaltungsmöglichkeit hat, dazu später mehr.

Als erstes legen wir eine JFrame-Klasse GridLayoutDemo an (wie im Kapitel matisse beschrieben) und weisen dem JPanel das GridLayout zu. Am einfachsten geht das durch Rechtsklick im Navigator auf das Panel und Auswahl von „Grid Layout“. Beachten Sie, dass der dort eingestellte Default das viel benützte, aber eigentlich wenig mächtige „Free Design“ ist. (Hinweis: im Kapitel matisse finden Sie den Hinweis auf den Navigator, entsprechende Schirmschüsse und eine Anleitung, falls er bei Ihnen ausgeblendet sein sollte)

Der Baum im Navigator erhält eine zusätzliche Ebene „GridLayout“, die wir wieder rechtsklicken und „Properties“ anwählen. Dort können wir Spalten und Zeilen jeweils auf 3 einstellen (Das sind die Einstellungen „Columns“ und „Rows“. Die „Gap“s bitte ignorieren – damit experimentieren Sie am besten nachher auf eigene Faust)

Um eine wortreiche und abstrakte Erklärung zu vermeiden, wie nun Komponenten verteilt werden, hier Bildschirmschüsse nach dem Einsetzen jedes einzelnen Elements in ein 3x3-Raster. Bei der folgenden Serie behalten Sie bitte im Hinterkopf, dass wir einen 3x3-Raster bereits vorher in den Eigenschaften des Layout-Managers festgelegt haben!

GridLayout Beispiel 1 GridLayout Beispiel 2

Beachten Sie, dass das GridLayout die Elemente grundsätzlich „aufbläst“, sodass sie ihre gesamte Zelle im Raster ausfüllen. Bei den hier verwendeten JButtons ist das sehr schön sichtbar, bei JLabels (die nur einen Text anzeigen), bemerkt man davon gar nichts – obwohl es passiert!

Jede Zelle nimmt nur ein einziges Element auf. Und weiter geht es, beim 4. Button wird es interessant:

GridLayout Beispiel 3 GridLayout Beispiel 2

Die drei Zeilen, die wir vorher angegeben hatten, waren ausgeschöpft, also beginnt das GridLayout eine neue Spalte.

Die Buttons 5-9 bieten jetzt keine Überraschungen mehr:

GridLayout Beispiel 5 GridLayout Beispiel 6
GridLayout Beispiel 7  

Beachten Sie, wie die Spaltenbreiten beim Wechsel von zwei auf drei Spalten angepasst werden!

Obwohl wir eingangs 3x3 festgelegt haben, könnten Sie weitere Elemente hinzufügen, das GridLayout beginnt in dem Fall eine 4. Spalte. In diesem Sinne wird es also niemals „voll“, allerdings ist es die wesentlich bessere Vorgangsweise, vorher Zeilen und Spalten festgelegt zu haben und das Grid wie geplant zu befüllen.

An dieser Stelle sei auch erwähnt, dass jedes beliebige Element verteilt werden darf, keineswegs nur JButtons! (Wir haben sie nur deswegen gewählt, weil sie das Ausfüllen der Zellen schön sichtbar machen).

Erinnern Sie sich an das „fast“? Die Gestaltungsmöglichkeit, die wir erwähnt haben, besteht darin, dass man Elemente nicht immer in die „letzte“ Zelle setzen muss, sondern unter den bereits vorhandenen Elementen wählen kann, ob man ein neues Element davor oder danach einsetzen will — eine Vorgangsweise, von der wir dringen abraten.

Nun ist ein Buttonraster allgemein gesprochen wenig hilfreich. Das GridLayout wird daher in den seltensten Fällen einzelne Elemente in seinen Zellen enthalten, dafür ist es viel zu unflexibel. Wenn man allerdings die hier benutzten JButtons bspw. durch JPanels ersetzt, die ihrerseits ein Bild und eine Bildunterschrift enthalten, dann kann man ahnen, wie einfach z.B. ein Thumbnail-Viewer mit einer regelmäßigen Anmutung aufgebaut werden kann, denn die Zellen des Grids skalieren mit der Größe des JFrame.

Fazit: Das GridLayout wird in den seltensten Fällen n×m Einzelelemente enthalten und damit die gesamte GUI zur Verfügung stellen. Meistens werden seine Zellen JPanels enthalten, und so ein unterteiltes aber regelmäßiges Userinterface darstellen. Natürlich kann es auch selbst in etwas Größeres eingebettet sein, was ebenfalls häufig der Fall sein wird.

Das obige Beispiel und die Schirmschüsse für das GridLayout wurden mit dem graphischen GUI-editor »matisse« erzeugt. Falls möglich, empfehlen wir den Versuch es nachzumachen, weil so am schnellsten ein guter Eindruck entsteht, wie das GridLayout Elemente anordnet. Programmiert man es ohne matisse, geht man im Grunde vollkommen gleich vor, wie dieser Code zeigt, der das gleiche Resultat erzeugt:

 
package gui;
 
/**
 * Demo für den Layout-Manager GridLayout.
 *
 * Wenn Sie dieses Codebeispiel zum Laufen bringen wollen, beachten Sie, dass
 * Sie den Quelltext in einer Datei namens GridLayoutDemo.java speichern
 * (Achtung auf Groß-und Kleinschreibung) und dass sich die Datei in einem
 * Unterordner „gui“ unter Ihrem Projektordner befinden muss.
 *
 * Die meisten Swing-Formulare leiten javax.swing.JFrame ab.
 *
 * @author phaidros
 */
public class GridLayoutDemo extends javax.swing.JFrame {
 
    // Die Objektvariablen für die Elemente auf dem JFrame:
 
    // Auf dem JPanel wird alles angeordnet.
    // Es ist das Element, dem das Flow-Layout zugewiesen wird
    private javax.swing.JPanel jPanel1 = new javax.swing.JPanel();
 
    // Die sichtbaren Elemente werden als Objektvariablen angelegt:
 
    // Wir *könnten* hier 9 JButtons erzeugen, aber wir nützen die Gelegenheit,
    // um unser Interface etwas pfiffiger aufzubauen: statt jButton1-jButton9
    // erzeugen wir *ein* Array JButton[9].
    //
    // Anm.: Der graphische GUI-editor matisse könnte dieses Interface so
    // gar nicht erzeugen: er kann nicht mit Arrays aus Elementen umgehen!
 
    // Anm.: Achtung! Hier werden keineswegs, wie man annehmen könnte,
    // 9 Buttons erzeugt, sondern *ein* Array (das ja als "Array" ein
    // eigenständiges Objekt ist. Die Buttons, um es zu befüllen, müssen erst
    // erzeugt werden.
    private javax.swing.JButton[] jButton = new javax.swing.JButton[9];
 
    /**
     * Der Konstruktor.
     */
    public GridLayoutDemo() {
 
        // Was soll bei Klick auf das System-X rechts oben passieren:
        // Das Programm soll gänzlich beendet werden.
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
 
        // Beachten Sie, dass Swing gar nicht so selten auf Elemente der
        // Vorgänger-Bibliothek 'awt' zugreift. Auch Das GridLayout
        // gehört eigentlich zum awt. 
        // Das JPanel bekommt sein Layout, in diesem Fall ein 3x3-Grid:
        jPanel1.setLayout( new java.awt.GridLayout( 3, 3 ) );
 
        // Der Vollständigkeit halber erzeugen wir auch eine Listener-Methode
        // (nicht das eigentliche Thema des Codebeispiels)
        // Alle 9 Buttons des JButton-array werden ein und denselben Listener
        // aufrufen – und zwar diesen hier:
        ButtonListener bl = new ButtonListener();
        // Buttonlistener ist eine eigene, "innere" Klasse, siehe weiter unten.
 
        // Hier werden die JButtons erzeugt und dem Panel hinzugefügt
        // Bemerkenswert: die Reihenfolge bestimmt, wie die Buttons im 3x3-Grid
        // verteilt werden.
        for ( int i = 0; i<9; i++ ) {
            jButton[i] = new javax.swing.JButton ( "JButton" + (i+1) );
            jButton[i].addActionListener ( bl );
            jPanel1.add ( jButton[i] );
        }
 
        // Das Panel zum aktiven, sichtbaren Inhalt des JFrame machen:
        this.getContentPane().add ( jPanel1 ) ;
 
        // Alle Elemente auf kleinstmögliche Größe bringen
        pack();
 
        // Anm.: Durch das pack() sieht dieses Beispiel etwas anders aus, als
        // das, das Sie ev. mit matisse zusammengebeut haben, weil die Buttons
        // klein sind. Aber wenn Sie das Fenster skalieren werden Sie sehen,
        // dass wir hier genau dasselbe Design erzeugt haben
    }
 
    // Da Java haufenweise »Events« erzeugt (von denen uns die meisten
    // nicht interessieren), müssen wir einen »ActionListener« programmieren,
    // der auf *bestimmte* Ereignisse hört (die uns eben interessieren)
    // Auch das Interface ActionListener ist in awt definiert.
    class ButtonListener implements java.awt.event.ActionListener {
        public void actionPerformed(java.awt.event.ActionEvent e) {
 
            // Wenn dieser Code aufgerufen wird wissenw wir, dass ein Button
            // geklickt wurde – aber *welcher*? Hier können Sie sehen, dass es
            // Situationen gibt, wo Objekte mit '==' verglichen werden!
            // (Objektidentität wird gefragt, nicht (nur) inhaltliche Identität!)
            for (int i=0; i<9; i++) {
                if( e.getSource() == jButton[i] ){
                    System.out.println("JButton" + (i+1) + " wurde geklickt.");
                }
            }
        }
    }
 
    /**
     * Zeigt ein JFrame mit einem 3x3-Grid aus JButtons an.
     * Jedes Java-Programm beginnt bei einer Methode main() zu laufen, so auch
     * dieses. Beachten Sie, dass die Methode main() in jeder beliebigen
     * Klasse stehen könnte, die Zugriff auf GridLayoutDemo hat, also auch in
     * ihr selbst – also hier:
     */
    public static void main(String args[]) {
        // Ein Objekt der Klasse erzeugen und sichtbar machen.
        new GridLayoutDemo().setVisible ( true );
    }   
}

Text, Code und Bilder © Phaidros (Gast-Autor)