GridLayout Live-Demo: Unterschied zwischen den Versionen

Aus Byte-Welt Wiki
Zur Navigation springenZur Suche springen
K
K
 
(12 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 1: Zeile 1:
 
[[Kategorie:Java-Codeschnipsel]]
 
[[Kategorie:Java-Codeschnipsel]]
Mit der [[GridLayout]] Live-Demo erkundet man beim Spielen mit Werten das Verhalten vom GridLayout durch sofortige Anpassung der programmierten Benutzeroberfläche.
+
[[Kategorie:LayoutManager]]
{{In Arbeit}}
+
'''Autor: Gernot Segieth'''
  
[[Datei:GridLayout-Live-Demo.png]]
+
Die GridLayout-Live-Demo erleichtert spielerisch durch Erkunden und Verändern von Werten in der Benutzeroberfläche das Verständnis von [[GridLayout]].
  
Mehr zum [[GridLayout]] und anderen [[LayoutManager der Standard-Java-API|LayoutManagern]]
+
Diese Demo enthält u.a. auch ein Beispiel, wie ein {{JAPI|JSpinner}} verwendet werden kann und wie man einfache Icons selbst zeichnet.
 +
 
 +
[[Datei:GridLayout-Live-Demo.gif]]
 +
 
 +
Kopieren Sie sich die Quellcodes in einzelne Java-Dateien. Achten Sie auf die richtige Verteilung der Klassen in die im Code angegebenen [[Java-Package|Packages]], oder kommentieren Sie die Package-Anweisung einfach aus, wenn Sie unsicher sind. Anschließend [[Java-Quellcode kompilieren|kompilieren]] Sie die Java-Dateien und [[Java-Anwendung starten|starten]] die Hauptklasse.
 +
 
 +
=GridLayoutDemo.java - Die Hauptklasse=
 +
<syntaxhighlight lang="java">
 +
/*
 +
* GridLayout-Live-Demo
 +
*
 +
* Copyright (c) 2019 Gernot Segieth - wiki.byte-welt.net
 +
*
 +
* Permission is hereby granted, free of charge, to any person
 +
* obtaining a copy of this software and associated documentation
 +
* files (the "Software"), to deal in the Software without
 +
* restriction, including without limitation the rights to use,
 +
* copy, modify, merge, publish, distribute, sublicense, and/or sell
 +
* copies of the Software, and to permit persons to whom the
 +
* Software is furnished to do so, subject to the following
 +
* conditions:
 +
*
 +
* The above copyright notice and this permission notice shall be
 +
* included in all copies or substantial portions of the Software.
 +
*
 +
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 +
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 +
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 +
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 +
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 +
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 +
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 +
* OTHER DEALINGS IN THE SOFTWARE.
 +
*/
 +
package gridlayout;
 +
 
 +
import gridlayout.event.AddAction;
 +
import gridlayout.event.ColumnCountChangeAction;
 +
import gridlayout.event.GridOperations;
 +
import gridlayout.event.HgapChangeAction;
 +
import gridlayout.event.RemoveAction;
 +
import gridlayout.event.RowCountChangeAction;
 +
import gridlayout.event.VgapChangeAction;
 +
import java.awt.BorderLayout;
 +
import java.awt.Color;
 +
import java.awt.Dimension;
 +
import java.awt.GridBagConstraints;
 +
import java.awt.GridBagLayout;
 +
import java.awt.GridLayout;
 +
import java.awt.Insets;
 +
import java.awt.Toolkit;
 +
import javax.swing.BorderFactory;
 +
import javax.swing.JButton;
 +
import javax.swing.JFrame;
 +
import javax.swing.JLabel;
 +
import javax.swing.JPanel;
 +
import javax.swing.JSpinner;
 +
import javax.swing.SpinnerNumberModel;
 +
import javax.swing.SwingUtilities;
 +
 
 +
/**
 +
* Die GridLayout-Live-Demo erleichtert spielerisch durch Erkunden und Verändern
 +
* von Werten in der Benutzeroberfläche das Verständnis von GridLayout.
 +
*
 +
* @author Gernot Segieth, (c)2019
 +
* @see java.awt.GridLayout
 +
*/
 +
public class GridLayoutDemo implements GridOperations {
 +
 
 +
    private JPanel gridPanel;
 +
    private GridLayout layout;
 +
    private SpinnerNumberModel hgapModel; //JSpinner zur Eingabe horizontaler Abstände
 +
    private SpinnerNumberModel vgapModel; //JSpinner zur Eingabe vertikaler Abstände
 +
    private SpinnerNumberModel rowModel; //JSpinner zur Eingabe der Zeilen im Gitter
 +
    private SpinnerNumberModel colModel; //JSpinner zur Eingabe der Spalten im Gitter 
 +
    private int compCount; //zählt die Komponenten 
 +
 
 +
    public GridLayoutDemo() {
 +
        JFrame frame = new JFrame("GridLayout (Live-Demo)");
 +
        frame.add(createGridPanel(), BorderLayout.CENTER);
 +
        frame.add(createControlPanel(), BorderLayout.NORTH);
 +
        frame.add(createSouthPanel(), BorderLayout.SOUTH);
 +
        frame.pack();
 +
        frame.setLocationRelativeTo(null);
 +
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
 +
        frame.setVisible(true);
 +
    }
 +
 
 +
    @Override
 +
    public void addComponent() {
 +
        gridPanel.add(new JButton(String.valueOf(++compCount)));
 +
        gridPanel.validate();
 +
        gridPanel.repaint();
 +
    }
 +
 
 +
    @Override
 +
    public void removeComponent() {
 +
        if (compCount > 0) {
 +
            gridPanel.remove(--compCount);
 +
            gridPanel.validate();
 +
            gridPanel.repaint();
 +
        }
 +
    }
 +
 
 +
    @Override
 +
    public void changeHgap() {
 +
        layout.setHgap((int) hgapModel.getNumber());
 +
        update();
 +
    }
 +
 
 +
    @Override
 +
    public void changeVgap() {
 +
        layout.setVgap((int) vgapModel.getNumber());
 +
        update();
 +
 
 +
    }
 +
 
 +
    @Override
 +
    public void changeRowCount() {
 +
        layout.setRows((int) rowModel.getNumber());
 +
        update();
 +
    }
 +
 
 +
    @Override
 +
    public void changeColumnCount() {
 +
        layout.setColumns((int) colModel.getNumber());
 +
        update();
 +
    }
 +
 
 +
    private JPanel createGridPanel() {
 +
        layout = new GridLayout();
 +
        gridPanel = new JPanel(layout) {
 +
            @Override
 +
            public Dimension getPreferredSize() {
 +
                Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
 +
                return new Dimension(size.width * 40 / 100, size.height * 40 / 100);
 +
            }
 +
        };
 +
        gridPanel.setBackground(Color.WHITE);
 +
        return gridPanel;
 +
    }
 +
 
 +
    private JPanel createControlPanel() {
 +
        JButton addButton = new JButton(new AddAction(this));
 +
        JButton removeButton = new JButton(new RemoveAction(this));
 +
 
 +
        hgapModel = new SpinnerNumberModel(layout.getHgap(), 0, 50, 1);
 +
        JSpinner hgapSpinner = new JSpinner(hgapModel);
 +
        hgapSpinner.addChangeListener(new HgapChangeAction(this));
 +
 
 +
        vgapModel = new SpinnerNumberModel(layout.getVgap(), 0, 50, 1);
 +
        JSpinner vgapSpinner = new JSpinner(vgapModel);
 +
        vgapSpinner.addChangeListener(new VgapChangeAction(this));
 +
 
 +
        rowModel = new SpinnerNumberModel(layout.getRows(), 0, 10, 1);
 +
        JSpinner rowSpinner = new JSpinner(rowModel);
 +
        rowSpinner.addChangeListener(new RowCountChangeAction(this));
 +
 
 +
        colModel = new SpinnerNumberModel(layout.getColumns(), 0, 10, 1);
 +
        JSpinner columnSpinner = new JSpinner(colModel);
 +
        columnSpinner.addChangeListener(new ColumnCountChangeAction(this));
 +
 
 +
        JPanel panel = new JPanel(new GridBagLayout());
 +
        panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
 +
        GridBagConstraints gbc = new GridBagConstraints();
 +
 
 +
        int space = 20;
 +
        gbc.gridx = 0;
 +
        gbc.gridy = 0;
 +
 
 +
        panel.add(new JLabel("setRows( "), gbc);
 +
 
 +
        gbc.gridx++;
 +
        panel.add(rowSpinner, gbc);
 +
 
 +
        gbc.insets = new Insets(0, 0, 0, space);
 +
        gbc.gridx++;
 +
        panel.add(new JLabel(" );"), gbc);
 +
 
 +
        gbc.insets = new Insets(0, 0, 0, 0);
 +
        gbc.gridx++;
 +
        panel.add(new JLabel("setColumns( "), gbc);
 +
 
 +
        gbc.gridx++;
 +
        panel.add(columnSpinner, gbc);
 +
 
 +
        gbc.insets = new Insets(0, 0, 0, space);
 +
        gbc.gridx++;
 +
        panel.add(new JLabel(" );"), gbc);
 +
 
 +
        gbc.insets = new Insets(0, 0, 0, 0);
 +
        gbc.gridx++;
 +
        panel.add(new JLabel("setHgap( "), gbc);
 +
 
 +
        gbc.gridx++;
 +
        panel.add(hgapSpinner, gbc);
 +
 
 +
        gbc.insets = new Insets(0, 0, 0, space);
 +
        gbc.gridx++;
 +
        panel.add(new JLabel(" );"), gbc);
 +
 
 +
        gbc.insets = new Insets(0, 0, 0, 0);
 +
        gbc.gridx++;
 +
        panel.add(new JLabel("setVgap( "), gbc);
 +
 
 +
        gbc.gridx++;
 +
        panel.add(vgapSpinner, gbc);
 +
 
 +
        gbc.insets = new Insets(0, 0, 0, space);
 +
        gbc.gridx++;
 +
        panel.add(new JLabel(" );"), gbc);
 +
 
 +
        panel.add(addButton);
 +
        panel.add(removeButton);
 +
 
 +
        return panel;
 +
    }
 +
 
 +
    private JPanel createSouthPanel() {
 +
        JLabel label = new JLabel("<html>&copy;2019 Gernot Segieth, Byte-Welt-Wiki (https://wiki.byte-welt.net)</html>");
 +
        label.setForeground(label.getBackground().darker());
 +
        label.setFont(label.getFont().deriveFont(10f));
 +
        JPanel panel = new JPanel();
 +
        panel.add(label);
 +
        return panel;
 +
    }
 +
 
 +
    private void update() {
 +
        SwingUtilities.invokeLater(() -> {
 +
            gridPanel.updateUI();
 +
        });
 +
    }
 +
 
 +
    public static void main(String[] args) {
 +
        JFrame.setDefaultLookAndFeelDecorated(true);
 +
        //UIManager.put("swing.boldMetal", false);
 +
        SwingUtilities.invokeLater(() -> {
 +
            new GridLayoutDemo();
 +
        });
 +
    }
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
=Klassen aus dem event-Package=
 +
Die im Folgenden aufgelisteten Quellcodes dienen der Reaktion auf Maus gesteuerte Ereignisse an der Benutzeroberfläche. Komponenten, die für sie bestimmte Aktionen erkennen, leiten die Informationen an die verarbeitenden [[Listener]] weiter. Diese wiederum sorgen dafür, dass [[Methode|Methoden]] als Reaktion auf die Manipulation der Benutzeroberfläche aufgerufen werden, die die Benutzeroberfläche entsprechend anpassen.
 +
 
 +
==Interface GridOperations - die Funktionen der Demo==
 +
<syntaxhighlight lang="java">
 +
package gridlayout.event;
 +
 
 +
/**
 +
*
 +
* @author Gernot Segieth
 +
*/
 +
public interface GridOperations {
 +
 
 +
    public void addComponent();
 +
 
 +
    public void removeComponent();
 +
 
 +
    public void changeHgap();
 +
 
 +
    public void changeVgap();
 +
 
 +
    public void changeRowCount();
 +
 
 +
    public void changeColumnCount();
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
==AddAction - Hinzufügen neuer Komponenten==
 +
<syntaxhighlight lang="java">
 +
package gridlayout.event;
 +
 
 +
import gridlayout.icons.MoreIcon;
 +
import java.awt.event.ActionEvent;
 +
import javax.swing.AbstractAction;
 +
 
 +
/**
 +
*
 +
* @author Gernot Segieth
 +
*/
 +
public class AddAction extends AbstractAction {
 +
 
 +
    private final GridOperations go;
 +
 
 +
    public AddAction(GridOperations go) {
 +
        super("", new MoreIcon());
 +
        this.go = go;
 +
    }
 +
 
 +
    @Override
 +
    public void actionPerformed(ActionEvent ae) {
 +
        go.addComponent();
 +
    }
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
==RemoveAction - Entfernen von Komponenten==
 +
<syntaxhighlight lang="java">
 +
package gridlayout.event;
 +
 
 +
import gridlayout.icons.LessIcon;
 +
import java.awt.event.ActionEvent;
 +
import javax.swing.AbstractAction;
 +
 
 +
/**
 +
*
 +
* @author Gernot Segieth
 +
*/
 +
public class RemoveAction extends AbstractAction {
 +
 
 +
    private final GridOperations go;
 +
 
 +
    public RemoveAction(GridOperations go) {
 +
        super("", new LessIcon());
 +
        this.go = go;
 +
    }
 +
 
 +
    @Override
 +
    public void actionPerformed(ActionEvent ae) {
 +
        go.removeComponent();
 +
    }
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
==HgapChangeAction - Horizontalen Abstand einstellen==
 +
<syntaxhighlight lang="java">
 +
package gridlayout.event;
 +
 
 +
import javax.swing.event.ChangeEvent;
 +
import javax.swing.event.ChangeListener;
 +
 
 +
/**
 +
*
 +
* @author Gernot Segieth
 +
*/
 +
public class HgapChangeAction implements ChangeListener {
 +
 
 +
    private final GridOperations go;
 +
 
 +
    public HgapChangeAction(GridOperations go) {
 +
        this.go = go;
 +
    }
 +
 
 +
    @Override
 +
    public void stateChanged(ChangeEvent ce) {
 +
        go.changeHgap();
 +
    }
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
==VgapChangeAction - Vertikalen Abstand einstellen==
 +
<syntaxhighlight lang="java">
 +
package gridlayout.event;
 +
 
 +
import javax.swing.event.ChangeEvent;
 +
import javax.swing.event.ChangeListener;
 +
 
 +
/**
 +
*
 +
* @author Gernot Segieth
 +
*/
 +
public class VgapChangeAction implements ChangeListener {
 +
 
 +
    private final GridOperations go;
 +
 
 +
    public VgapChangeAction(GridOperations go) {
 +
        this.go = go;
 +
    }
 +
 
 +
    @Override
 +
    public void stateChanged(ChangeEvent ce) {
 +
        go.changeVgap();
 +
    }
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
==RowCountChangeAction - Anzahl der Zeilen im Gitter einstellen==
 +
 
 +
<syntaxhighlight lang="java">
 +
package gridlayout.event;
 +
 
 +
import javax.swing.event.ChangeEvent;
 +
import javax.swing.event.ChangeListener;
 +
 
 +
/**
 +
*
 +
* @author Gernot Segieth
 +
*/
 +
public class RowCountChangeAction implements ChangeListener {
 +
 
 +
    private final GridOperations go;
 +
 
 +
    public RowCountChangeAction(GridOperations go) {
 +
        this.go = go;
 +
    }
 +
 
 +
    @Override
 +
    public void stateChanged(ChangeEvent ce) {
 +
        go.changeRowCount();
 +
    }
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
==ColumnCountChangeAction -  Anzahl der Spalten im Gitter einstellen==
 +
<syntaxhighlight lang="java">
 +
package gridlayout.event;
 +
 
 +
import javax.swing.event.ChangeEvent;
 +
import javax.swing.event.ChangeListener;
 +
 
 +
/**
 +
*
 +
* @author Gernot Segieth
 +
*/
 +
public class ColumnCountChangeAction implements ChangeListener {
 +
 
 +
    private final GridOperations go;
 +
 
 +
    public ColumnCountChangeAction(GridOperations go) {
 +
        this.go = go;
 +
    }
 +
 
 +
    @Override
 +
    public void stateChanged(ChangeEvent ce) {
 +
        go.changeColumnCount();
 +
    }
 +
 
 +
}
 +
</syntaxhighlight>
 +
 
 +
=Icons=
 +
Fehlen nur noch die Icons, die auch als Java-Klasse angelegt werden können.
 +
 
 +
Dieses Codestück zeigt, wie man ein einfaches Icon selbst zeichnet. Hier zeichnen wir ein Minus-Symbol in den JButton.
 +
 
 +
Zunächst das Minus-Icon:
 +
<syntaxhighlight lang="java">
 +
package gridlayout.icons;
 +
 
 +
import java.awt.BasicStroke;
 +
import java.awt.Component;
 +
import java.awt.Graphics;
 +
import java.awt.Graphics2D;
 +
import java.awt.Shape;
 +
import java.awt.geom.AffineTransform;
 +
import java.awt.geom.GeneralPath;
 +
import java.awt.geom.Path2D;
 +
import javax.swing.Icon;
 +
 
 +
public class LessIcon implements Icon {
 +
 
 +
    @Override
 +
    public void paintIcon(Component c, Graphics gr, int x, int y) {
 +
        Graphics2D g = (Graphics2D) gr;
 +
        AffineTransform at = new AffineTransform();
 +
        at.translate(x, y);
 +
        at.scale(getIconWidth(), getIconHeight());
 +
        Shape transformedShape = at.createTransformedShape(createShape());
 +
        g.setStroke(new BasicStroke(2));
 +
        g.draw(transformedShape);
 +
        g.dispose();
 +
    }
 +
 
 +
    @Override
 +
    public int getIconWidth() {
 +
        return 15;
 +
    }
 +
 
 +
    @Override
 +
    public int getIconHeight() {
 +
        return getIconWidth();
 +
    }
 +
 
 +
    private Shape createShape() {
 +
        Path2D path = new GeneralPath();
 +
        path.moveTo(0.1f, 0.5f);
 +
        path.lineTo(0.9f, 0.5f);
 +
        return path;
 +
    }
 +
}
 +
</syntaxhighlight>
 +
 
 +
Dieses Codestück zeigt, wie man ein einfaches Icon selbst zeichnet. Hier zeichnen wir ein Plus-Symbol in den JButton.
 +
 
 +
Das Plus-Icon:
 +
<syntaxhighlight lang="java">
 +
package gridlayout.icons;
 +
 
 +
import java.awt.BasicStroke;
 +
import java.awt.Component;
 +
import java.awt.Graphics;
 +
import java.awt.Graphics2D;
 +
import java.awt.Shape;
 +
import java.awt.geom.AffineTransform;
 +
import java.awt.geom.GeneralPath;
 +
import java.awt.geom.Path2D;
 +
import javax.swing.Icon;
 +
 
 +
public class MoreIcon implements Icon {
 +
 
 +
    @Override
 +
    public void paintIcon(Component c, Graphics gr, int x, int y) {
 +
        Graphics2D g = (Graphics2D) gr;
 +
        AffineTransform at = new AffineTransform();
 +
        at.translate(x, y);
 +
        at.scale(getIconWidth(), getIconHeight());
 +
        Shape transformedShape = at.createTransformedShape(createShape());
 +
        g.setStroke(new BasicStroke(2));
 +
        g.draw(transformedShape);
 +
        g.dispose();
 +
    }
 +
 
 +
    @Override
 +
    public int getIconWidth() {
 +
        return 15;
 +
    }
 +
 
 +
    @Override
 +
    public int getIconHeight() {
 +
        return getIconWidth();
 +
    }
 +
 
 +
    private Shape createShape() {
 +
        Path2D path = new GeneralPath();
 +
        path.moveTo(0.5f, 0.1f);
 +
        path.lineTo(0.5f, 0.9f);
 +
        path.moveTo(0.1f, 0.5f);
 +
        path.lineTo(0.9f, 0.5f);
 +
        return path;
 +
    }
 +
}
 +
 
 +
</syntaxhighlight>
 +
 
 +
<syntaxhighlight lang="java">
 +
 
 +
</syntaxhighlight>
 +
 
 +
 
 +
{{Fragen stellen}}
 +
 
 +
=Weiterführende Links=
 +
*Mehr zum [[GridLayout]] und anderen [[LayoutManager der Standard-Java-API|LayoutManagern]]
 +
*[[JSpinner mit Zahl und Einheit]]
 +
 
 +
<syntaxhighlight lang="java">
 +
 
 +
</syntaxhighlight>

Aktuelle Version vom 14. November 2021, 17:09 Uhr

Autor: Gernot Segieth

Die GridLayout-Live-Demo erleichtert spielerisch durch Erkunden und Verändern von Werten in der Benutzeroberfläche das Verständnis von GridLayout.

Diese Demo enthält u.a. auch ein Beispiel, wie ein JSpinner verwendet werden kann und wie man einfache Icons selbst zeichnet.

GridLayout-Live-Demo.gif

Kopieren Sie sich die Quellcodes in einzelne Java-Dateien. Achten Sie auf die richtige Verteilung der Klassen in die im Code angegebenen Packages, oder kommentieren Sie die Package-Anweisung einfach aus, wenn Sie unsicher sind. Anschließend kompilieren Sie die Java-Dateien und starten die Hauptklasse.

GridLayoutDemo.java - Die Hauptklasse

/*
 * GridLayout-Live-Demo
 *
 * Copyright (c) 2019 Gernot Segieth - wiki.byte-welt.net
 * 
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
package gridlayout;

import gridlayout.event.AddAction;
import gridlayout.event.ColumnCountChangeAction;
import gridlayout.event.GridOperations;
import gridlayout.event.HgapChangeAction;
import gridlayout.event.RemoveAction;
import gridlayout.event.RowCountChangeAction;
import gridlayout.event.VgapChangeAction;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.GridLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;

/**
 * Die GridLayout-Live-Demo erleichtert spielerisch durch Erkunden und Verändern
 * von Werten in der Benutzeroberfläche das Verständnis von GridLayout.
 *
 * @author Gernot Segieth, (c)2019
 * @see java.awt.GridLayout
 */
public class GridLayoutDemo implements GridOperations {

    private JPanel gridPanel;
    private GridLayout layout;
    private SpinnerNumberModel hgapModel; //JSpinner zur Eingabe horizontaler Abstände
    private SpinnerNumberModel vgapModel; //JSpinner zur Eingabe vertikaler Abstände
    private SpinnerNumberModel rowModel; //JSpinner zur Eingabe der Zeilen im Gitter
    private SpinnerNumberModel colModel; //JSpinner zur Eingabe der Spalten im Gitter   
    private int compCount; //zählt die Komponenten   

    public GridLayoutDemo() {
        JFrame frame = new JFrame("GridLayout (Live-Demo)");
        frame.add(createGridPanel(), BorderLayout.CENTER);
        frame.add(createControlPanel(), BorderLayout.NORTH);
        frame.add(createSouthPanel(), BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
        frame.setVisible(true);
    }

    @Override
    public void addComponent() {
        gridPanel.add(new JButton(String.valueOf(++compCount)));
        gridPanel.validate();
        gridPanel.repaint();
    }

    @Override
    public void removeComponent() {
        if (compCount > 0) {
            gridPanel.remove(--compCount);
            gridPanel.validate();
            gridPanel.repaint();
        }
    }

    @Override
    public void changeHgap() {
        layout.setHgap((int) hgapModel.getNumber());
        update();
    }

    @Override
    public void changeVgap() {
        layout.setVgap((int) vgapModel.getNumber());
        update();

    }

    @Override
    public void changeRowCount() {
        layout.setRows((int) rowModel.getNumber());
        update();
    }

    @Override
    public void changeColumnCount() {
        layout.setColumns((int) colModel.getNumber());
        update();
    }

    private JPanel createGridPanel() {
        layout = new GridLayout();
        gridPanel = new JPanel(layout) {
            @Override
            public Dimension getPreferredSize() {
                Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
                return new Dimension(size.width * 40 / 100, size.height * 40 / 100);
            }
        };
        gridPanel.setBackground(Color.WHITE);
        return gridPanel;
    }

    private JPanel createControlPanel() {
        JButton addButton = new JButton(new AddAction(this));
        JButton removeButton = new JButton(new RemoveAction(this));

        hgapModel = new SpinnerNumberModel(layout.getHgap(), 0, 50, 1);
        JSpinner hgapSpinner = new JSpinner(hgapModel);
        hgapSpinner.addChangeListener(new HgapChangeAction(this));

        vgapModel = new SpinnerNumberModel(layout.getVgap(), 0, 50, 1);
        JSpinner vgapSpinner = new JSpinner(vgapModel);
        vgapSpinner.addChangeListener(new VgapChangeAction(this));

        rowModel = new SpinnerNumberModel(layout.getRows(), 0, 10, 1);
        JSpinner rowSpinner = new JSpinner(rowModel);
        rowSpinner.addChangeListener(new RowCountChangeAction(this));

        colModel = new SpinnerNumberModel(layout.getColumns(), 0, 10, 1);
        JSpinner columnSpinner = new JSpinner(colModel);
        columnSpinner.addChangeListener(new ColumnCountChangeAction(this));

        JPanel panel = new JPanel(new GridBagLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(10, 0, 10, 0));
        GridBagConstraints gbc = new GridBagConstraints();

        int space = 20;
        gbc.gridx = 0;
        gbc.gridy = 0;

        panel.add(new JLabel("setRows( "), gbc);

        gbc.gridx++;
        panel.add(rowSpinner, gbc);

        gbc.insets = new Insets(0, 0, 0, space);
        gbc.gridx++;
        panel.add(new JLabel(" );"), gbc);

        gbc.insets = new Insets(0, 0, 0, 0);
        gbc.gridx++;
        panel.add(new JLabel("setColumns( "), gbc);

        gbc.gridx++;
        panel.add(columnSpinner, gbc);

        gbc.insets = new Insets(0, 0, 0, space);
        gbc.gridx++;
        panel.add(new JLabel(" );"), gbc);

        gbc.insets = new Insets(0, 0, 0, 0);
        gbc.gridx++;
        panel.add(new JLabel("setHgap( "), gbc);

        gbc.gridx++;
        panel.add(hgapSpinner, gbc);

        gbc.insets = new Insets(0, 0, 0, space);
        gbc.gridx++;
        panel.add(new JLabel(" );"), gbc);

        gbc.insets = new Insets(0, 0, 0, 0);
        gbc.gridx++;
        panel.add(new JLabel("setVgap( "), gbc);

        gbc.gridx++;
        panel.add(vgapSpinner, gbc);

        gbc.insets = new Insets(0, 0, 0, space);
        gbc.gridx++;
        panel.add(new JLabel(" );"), gbc);

        panel.add(addButton);
        panel.add(removeButton);

        return panel;
    }

    private JPanel createSouthPanel() {
        JLabel label = new JLabel("<html>&copy;2019 Gernot Segieth, Byte-Welt-Wiki (https://wiki.byte-welt.net)</html>");
        label.setForeground(label.getBackground().darker());
        label.setFont(label.getFont().deriveFont(10f));
        JPanel panel = new JPanel();
        panel.add(label);
        return panel;
    }

    private void update() {
        SwingUtilities.invokeLater(() -> {
            gridPanel.updateUI();
        });
    }

    public static void main(String[] args) {
        JFrame.setDefaultLookAndFeelDecorated(true);
        //UIManager.put("swing.boldMetal", false);
        SwingUtilities.invokeLater(() -> {
            new GridLayoutDemo();
        });
    }

}

Klassen aus dem event-Package

Die im Folgenden aufgelisteten Quellcodes dienen der Reaktion auf Maus gesteuerte Ereignisse an der Benutzeroberfläche. Komponenten, die für sie bestimmte Aktionen erkennen, leiten die Informationen an die verarbeitenden Listener weiter. Diese wiederum sorgen dafür, dass Methoden als Reaktion auf die Manipulation der Benutzeroberfläche aufgerufen werden, die die Benutzeroberfläche entsprechend anpassen.

Interface GridOperations - die Funktionen der Demo

package gridlayout.event;

/**
 *
 * @author Gernot Segieth
 */
public interface GridOperations {

    public void addComponent();

    public void removeComponent();

    public void changeHgap();

    public void changeVgap();

    public void changeRowCount();

    public void changeColumnCount();

}

AddAction - Hinzufügen neuer Komponenten

package gridlayout.event;

import gridlayout.icons.MoreIcon;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;

/**
 *
 * @author Gernot Segieth
 */
public class AddAction extends AbstractAction {

    private final GridOperations go;

    public AddAction(GridOperations go) {
        super("", new MoreIcon());
        this.go = go;
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        go.addComponent();
    }

}

RemoveAction - Entfernen von Komponenten

package gridlayout.event;

import gridlayout.icons.LessIcon;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;

/**
 *
 * @author Gernot Segieth
 */
public class RemoveAction extends AbstractAction {

    private final GridOperations go;

    public RemoveAction(GridOperations go) {
        super("", new LessIcon());
        this.go = go;
    }

    @Override
    public void actionPerformed(ActionEvent ae) {
        go.removeComponent();
    }

}

HgapChangeAction - Horizontalen Abstand einstellen

package gridlayout.event;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 *
 * @author Gernot Segieth
 */
public class HgapChangeAction implements ChangeListener {

    private final GridOperations go;

    public HgapChangeAction(GridOperations go) {
        this.go = go;
    }

    @Override
    public void stateChanged(ChangeEvent ce) {
        go.changeHgap();
    }

}

VgapChangeAction - Vertikalen Abstand einstellen

package gridlayout.event;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 *
 * @author Gernot Segieth
 */
public class VgapChangeAction implements ChangeListener {

    private final GridOperations go;

    public VgapChangeAction(GridOperations go) {
        this.go = go;
    }

    @Override
    public void stateChanged(ChangeEvent ce) {
        go.changeVgap();
    }

}

RowCountChangeAction - Anzahl der Zeilen im Gitter einstellen

package gridlayout.event;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 *
 * @author Gernot Segieth
 */
public class RowCountChangeAction implements ChangeListener {

    private final GridOperations go;

    public RowCountChangeAction(GridOperations go) {
        this.go = go;
    }

    @Override
    public void stateChanged(ChangeEvent ce) {
        go.changeRowCount();
    }

}

ColumnCountChangeAction - Anzahl der Spalten im Gitter einstellen

package gridlayout.event;

import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 *
 * @author Gernot Segieth
 */
public class ColumnCountChangeAction implements ChangeListener {

    private final GridOperations go;

    public ColumnCountChangeAction(GridOperations go) {
        this.go = go;
    }

    @Override
    public void stateChanged(ChangeEvent ce) {
        go.changeColumnCount();
    }

}

Icons

Fehlen nur noch die Icons, die auch als Java-Klasse angelegt werden können.

Dieses Codestück zeigt, wie man ein einfaches Icon selbst zeichnet. Hier zeichnen wir ein Minus-Symbol in den JButton.

Zunächst das Minus-Icon:

package gridlayout.icons;

import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import javax.swing.Icon;

public class LessIcon implements Icon {

    @Override
    public void paintIcon(Component c, Graphics gr, int x, int y) {
        Graphics2D g = (Graphics2D) gr;
        AffineTransform at = new AffineTransform();
        at.translate(x, y);
        at.scale(getIconWidth(), getIconHeight());
        Shape transformedShape = at.createTransformedShape(createShape());
        g.setStroke(new BasicStroke(2));
        g.draw(transformedShape);
        g.dispose();
    }

    @Override
    public int getIconWidth() {
        return 15;
    }

    @Override
    public int getIconHeight() {
        return getIconWidth();
    }

    private Shape createShape() {
        Path2D path = new GeneralPath();
        path.moveTo(0.1f, 0.5f);
        path.lineTo(0.9f, 0.5f);
        return path;
    }
}

Dieses Codestück zeigt, wie man ein einfaches Icon selbst zeichnet. Hier zeichnen wir ein Plus-Symbol in den JButton.

Das Plus-Icon:

package gridlayout.icons;

import java.awt.BasicStroke;
import java.awt.Component;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Shape;
import java.awt.geom.AffineTransform;
import java.awt.geom.GeneralPath;
import java.awt.geom.Path2D;
import javax.swing.Icon;

public class MoreIcon implements Icon {

    @Override
    public void paintIcon(Component c, Graphics gr, int x, int y) {
        Graphics2D g = (Graphics2D) gr;
        AffineTransform at = new AffineTransform();
        at.translate(x, y);
        at.scale(getIconWidth(), getIconHeight());
        Shape transformedShape = at.createTransformedShape(createShape());
        g.setStroke(new BasicStroke(2));
        g.draw(transformedShape);
        g.dispose();
    }

    @Override
    public int getIconWidth() {
        return 15;
    }

    @Override
    public int getIconHeight() {
        return getIconWidth();
    }

    private Shape createShape() {
        Path2D path = new GeneralPath();
        path.moveTo(0.5f, 0.1f);
        path.lineTo(0.5f, 0.9f);
        path.moveTo(0.1f, 0.5f);
        path.lineTo(0.9f, 0.5f);
        return path;
    }
}


Fragen

Das Thema wurde nicht ausreichend behandelt? Du hast Fragen dazu und brauchst weitere Informationen? Lass Dir von uns helfen!

Wir helfen dir gerne!


Dir hat dieser Artikel gefallen? Oder Du hast Fehler entdeckt und möchtest zur Berichtigung beitragen? Prima! Schreibe einen Kommentar!

Du musst angemeldet sein, um einen Kommentar abzugeben.


Weiterführende Links