Ein JSpinner für Bilder
Ein JSpinner
ist eine einzeilige,
editierbare Auswahlkomponente. Er verwendet zur
Darstellung seiner Inhalte ein JFormattedTextField
.
Somit eignen sich hierfür standardmäßig
nur textbasierte Werte.
Das Textfeld ist, je nach
Charakter des darzustellenden Inhaltes, in einem
spezialisierten Editor gekapselt, dessen Typ von JSpinner.DefaultEditor
abgeleitet ist. Dieser wiederum stellt ein JPanel
dar, auf dem das erwähnte Textfeld positioniert
ist.
Durch Austausch des Textfeldes gegen eine
andere Darstellungskomponente und einigen weiteren
kleineren Anpassungen lässt sich ein JSpinner
auch für nicht textbasierte Objekte verwenden.
class ImageEditor extends JPanel { public ImageEditor(ImageSpinner spinner) { JLabel label = new JLabel(); label.setIcon((ImageIcon) spinner.getValue()); spinner.addChangeListener(e -> label.setIcon((ImageIcon) spinner.getValue())); String toolTipText = spinner.getToolTipText(); if (toolTipText != null) { label.setToolTipText(toolTipText); } add(label); } }
Die Klasse des Editors ist, wie beschrieben, von JPanel
abgeleitet. Ihm wird zur Aufnahme der Bilder ein JLabel
hinzugefügt. Um auf die Aktivität der
Schaltflächen zu reagieren, wird der Spinner bei
einem ChangeListener
angemeldet, in dessen
Methode stateChanged()
die jeweils aktuelle
Bilddatei dem Label übergeben wird.
Die Bilddateien selbst werden in Form von ImageIcon
-Objekten
geladen. Sie werden durch die Klasse SpinnerListModel
verwaltet, bei dem lediglich die Konstruktoren und
Accessormethoden des Models angepasst werden
müssen. Zur Steuerung der Dateireihenfolge des
Spinners dient ein numerischer Index, der in getNextValue()
und getPreviousValue()
gleich rotierend
inkremetiert oder dekrementiert wird.
class ImageListModel extends SpinnerListModel { private List<ImageIcon> list; private int index; public ImageListModel() { this(new ImageIcon[] { null }); } public ImageListModel(ImageIcon[] images) { this(Arrays.asList(images)); } public ImageListModel(List<ImageIcon> images) { super(images); this.list = images; this.index = 0; } @Override public Object getValue() { return (ImageIcon) list.get(index); } @Override public Object getNextValue() { index = (index >= (list.size() - 1)) ? 0 : (index + 1); return (ImageIcon) list.get(index); } @Override public Object getPreviousValue() { index = (index <= 0) ? list.size() - 1 : (index - 1); return (ImageIcon) list.get(index); } }
Es verbleibt die Anpassung des Spinners selbst. Hierzu
müssen in der JSpinner
-Klasse, neben
der Anpassung der Konstruktoren, ebenfalls nur die
Methoden setEditor()
und setModel()
überschrieben werden, um die Sicherheitsabfragen
auf die neuen Model- und Editor-Klassen anzupassen.
@Override public void setModel(SpinnerModel model) { super.setModel(model); if (!(model instanceof ImageListModel)) throw new IllegalArgumentException("Model must be of type ImageListModel"); } @Override public void setEditor(JComponent editor) { super.setEditor(editor); if (!(editor instanceof ImageEditor)) throw new IllegalArgumentException("Editor must be of type ImageEditor"); }
Vollständiger Quelltext
Nicht vergessen, den Pfad zu den Bilddateien in loadImg()
anzupassen!
import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Arrays; import java.util.List; import javax.imageio.ImageIO; import javax.swing.ImageIcon; import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JSpinner; import javax.swing.SpinnerListModel; import javax.swing.SpinnerModel; import javax.swing.SwingUtilities; public class SpinnerMitBildern { public SpinnerMitBildern() { init(); } public void init() { ImageSpinner spinner = new ImageSpinner(new ImageListModel(loadImg())); JFrame frame = new JFrame("JSpinner mit Bildern"); frame.add(spinner); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } private ImageIcon[] loadImg() { BufferedImage img = null; ImageIcon[] images = new ImageIcon[4]; try { for (int i = 0; i < images.length; i++) { img = ImageIO.read(getClass().getResource("../../img/js" + i + ".png")); images[i] = new ImageIcon(img); } } catch (IOException e) { e.printStackTrace(); } return images; } public static void main(String[] args) { SwingUtilities.invokeLater(() -> new SpinnerMitBildern()); } } class ImageListModel extends SpinnerListModel { private List<ImageIcon> list; private int index; public ImageListModel() { this(new ImageIcon[] { null }); } public ImageListModel(ImageIcon[] images) { this(Arrays.asList(images)); } public ImageListModel(List<ImageIcon> images) { super(images); this.list = images; this.index = 0; } @Override public Object getValue() { return (ImageIcon) list.get(index); } @Override public Object getNextValue() { index = (index >= (list.size() - 1)) ? 0 : (index + 1); return (ImageIcon) list.get(index); } @Override public Object getPreviousValue() { index = (index <= 0) ? list.size() - 1 : (index - 1); return (ImageIcon) list.get(index); } } class ImageEditor extends JPanel { public ImageEditor(ImageSpinner spinner) { JLabel label = new JLabel(); label.setIcon((ImageIcon) spinner.getValue()); spinner.addChangeListener(e -> label.setIcon((ImageIcon) spinner.getValue())); String toolTipText = spinner.getToolTipText(); if (toolTipText != null) { label.setToolTipText(toolTipText); } add(label); } } class ImageSpinner extends JSpinner { public ImageSpinner() { this(new ImageListModel()); } public ImageSpinner(ImageListModel model) { super(model); setEditor(new ImageEditor(this)); } @Override public void setModel(SpinnerModel model) { super.setModel(model); if (!(model instanceof ImageListModel)) throw new IllegalArgumentException("Model must be of type ImageListModel"); } @Override public void setEditor(JComponent editor) { super.setEditor(editor); if (!(editor instanceof ImageEditor)) throw new IllegalArgumentException("Editor must be of type ImageEditor"); } }
Wenn Ihnen javabeginners.de gefällt, freue ich mich über eine Spende an diese gemeinnützigen Organisationen.