FlowLayout Live-Demo
Aus Byte-Welt Wiki
Autor: Gernot Segieth
Die FlowLayout-Live-Demo erleichtert spielerisch durch Erkunden und Verändern von Werten in der Benutzeroberfläche das Verständnis von FlowLayout.
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.
FlowLayoutDemo.java - Die Hauptklasse
[Bearbeiten | Quelltext bearbeiten]/*
* FlowLayout-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 flowlayout;
import flowlayout.event.AddAction;
import flowlayout.event.FlowOperations;
import flowlayout.event.HgapChangeAction;
import flowlayout.event.RemoveAction;
import flowlayout.event.SelectAction;
import flowlayout.event.VgapChangeAction;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Toolkit;
import javax.swing.BorderFactory;
import javax.swing.ComboBoxModel;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
/**
* Die FlowLayout-Live-Demo erleichtert spielerisch durch Erkunden und Verändern
* von Werten in der Benutzeroberfläche das Verständnis von FlowLayout.
*
* @author Gernot Segieth, (c)2019
* @see java.awt.FlowLayout
*/
public class FlowLayoutDemo implements FlowOperations {
private JPanel flowPanel;
private FlowLayout layout;
private SpinnerNumberModel hgapModel; //JSpinner zur Eingabe horizontaler Abstände
private SpinnerNumberModel vgapModel; //JSpinner zur Eingabe vertikaler Abstände
private ComboBoxModel<Integer> alignArgumentModel;
private int compCount; //zählt die Komponenten
public FlowLayoutDemo() {
JFrame frame = new JFrame("FlowLayout (Live-Demo)");
frame.add(createFlowPanel(), 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() {
flowPanel.add(new JButton("JButton " + (++compCount)));
flowPanel.validate();
flowPanel.repaint();
}
@Override
public void removeComponent() {
if (compCount > 0) {
flowPanel.remove(--compCount);
flowPanel.validate();
flowPanel.repaint();
}
}
@Override
public void changeAlignment() {
int alignment = (Integer) alignArgumentModel.getSelectedItem();
layout.setAlignment(alignment);
update();
}
@Override
public void changeHgap() {
layout.setHgap((int) hgapModel.getNumber());
update();
}
@Override
public void changeVgap() {
layout.setVgap((int) vgapModel.getNumber());
update();
}
private JPanel createFlowPanel() {
layout = new FlowLayout();
flowPanel = new JPanel(layout) {
@Override
public Dimension getPreferredSize() {
Dimension size = Toolkit.getDefaultToolkit().getScreenSize();
return new Dimension(size.width * 40 / 100, size.height * 40 / 100);
}
};
flowPanel.setBackground(Color.WHITE);
return flowPanel;
}
private JPanel createControlPanel() {
JButton addButton = new JButton(new AddAction(this));
JButton removeButton = new JButton(new RemoveAction(this));
alignArgumentModel = createComboBoxModel();
JComboBox<Integer> alignBox = new JComboBox<>(alignArgumentModel);
alignBox.setEditable(false);
alignBox.setRenderer(new AlignmentComboBoxRenderer());
alignBox.addActionListener(new SelectAction(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));
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;
gbc.gridx++;
panel.add(new JLabel("<html>setAlignment(<strong>FlowLayout.</strong></html> "), gbc);
gbc.gridx++;
panel.add(alignBox, 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>©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 ComboBoxModel<Integer> createComboBoxModel() {
Integer[] items = new Integer[]{
FlowLayout.CENTER,
FlowLayout.LEADING,
FlowLayout.LEFT,
FlowLayout.RIGHT,
FlowLayout.TRAILING
};
alignArgumentModel = new DefaultComboBoxModel<>(items);
alignArgumentModel.setSelectedItem(layout.getAlignment());
return alignArgumentModel;
}
private void update() {
SwingUtilities.invokeLater(() -> {
flowPanel.updateUI();
});
}
public static void main(String[] args) {
JFrame.setDefaultLookAndFeelDecorated(true);
UIManager.put("swing.boldMetal", false);
SwingUtilities.invokeLater(() -> {
new FlowLayoutDemo();
});
}
}
Klassen aus dem Event-Package
[Bearbeiten | Quelltext bearbeiten]Interface FlowOperations - die Funktionen der Demo
[Bearbeiten | Quelltext bearbeiten]package flowlayout.event;
/**
*
* @author Gernot Segieth
*/
public interface FlowOperations {
public void addComponent();
public void removeComponent();
public void changeAlignment();
public void changeHgap();
public void changeVgap();
}
AddAction - Hinzufügen neuer Komponenten
[Bearbeiten | Quelltext bearbeiten]package flowlayout.event;
import gridlayout.icons.MoreIcon;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
/**
*
* @author Gernot Segieth
*/
public class AddAction extends AbstractAction {
private final FlowOperations fo;
public AddAction(FlowOperations fo) {
super("", new MoreIcon());
this.fo = fo;
}
@Override
public void actionPerformed(ActionEvent ae) {
fo.addComponent();
}
}
RemoveAction - Entfernen von Komponenten
[Bearbeiten | Quelltext bearbeiten]package flowlayout.event;
import gridlayout.icons.LessIcon;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
/**
*
* @author Gernot Segieth
*/
public class RemoveAction extends AbstractAction {
private final FlowOperations fo;
public RemoveAction(FlowOperations fo) {
super("", new LessIcon());
this.fo = fo;
}
@Override
public void actionPerformed(ActionEvent ae) {
fo.removeComponent();
}
}
SelectAction - Auswahl in der JComboBox behandeln
[Bearbeiten | Quelltext bearbeiten]package flowlayout.event;
import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
/**
*
* @author Gernot Segieth
*/
public class SelectAction extends AbstractAction {
private final FlowOperations fo;
public SelectAction(FlowOperations fo) {
this.fo = fo;
}
@Override
public void actionPerformed(ActionEvent ae) {
fo.changeAlignment();
}
}
HgapChangeAction - Horizontalen Abstand einstellen
[Bearbeiten | Quelltext bearbeiten]package flowlayout.event;
import javax.swing.event.ChangeEvent;
/**
*
* @author Gernot Segieth
*/
public class HgapChangeAction extends AbstractChangeAction {
private FlowOperations fo;
public HgapChangeAction(FlowOperations fo) {
this.fo = fo;
}
@Override
public void stateChanged(ChangeEvent ce) {
fo.changeHgap();
}
}
VgapChangeAction - Vertikalen Abstand einstellen
[Bearbeiten | Quelltext bearbeiten]package flowlayout.event;
import javax.swing.event.ChangeEvent;
/**
*
* @author Gernot Segieth
*/
public class VgapChangeAction extends AbstractChangeAction {
private FlowOperations fo;
public VgapChangeAction(FlowOperations fo) {
this.fo = fo;
}
@Override
public void stateChanged(ChangeEvent ce) {
fo.changeVgap();
}
}
Ein Renderer für die JComboBox
[Bearbeiten | Quelltext bearbeiten]package flowlayout;
import java.awt.Component;
import java.awt.FlowLayout;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JList;
/**
*
* @author Gernot Segieth
*/
public class AlignmentComboBoxRenderer extends DefaultListCellRenderer {
@Override
public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (value instanceof Integer) {
Integer intValue = (Integer) value;
switch (intValue) {
case FlowLayout.LEADING:
this.setText("LEADING");
break;
case FlowLayout.LEFT:
this.setText("LEFT");
break;
case FlowLayout.RIGHT:
this.setText("RIGHT");
break;
case FlowLayout.TRAILING:
this.setText("TRAILING");
break;
default:
this.setText("CENTER");
}
}
return this;
}
}
Icons
[Bearbeiten | Quelltext bearbeiten]Fehlen nur noch die Icons, die auch als Java-Klasse angelegt werden können.
Zunächst das Minus-Icon:
package flowlayout.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;
}
}
Das Plus-Icon:
package flowlayout.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
[Quelltext bearbeiten]Das Thema wurde nicht ausreichend behandelt? Du hast Fragen dazu und brauchst weitere Informationen? Lass Dir von uns helfen!
- Besuche unseren Chat
Wir helfen dir gerne!
Weiterführende Links
[Bearbeiten | Quelltext bearbeiten]- Mehr zum FlowLayout und anderen LayoutManagern
- JSpinner mit Zahl und Einheit

