Custom Events in Swing
Willemers Informatik-Ecke
Zurück zur Java-Hauptseite Weitere Java-Themen

Ein eigenes Kontrollelement

Im Beispiel wird ein eigenes Kontrollelement definiert, das eine Farbauswahl des Benutzers erlauben soll. Dabei soll es die aktuelle Farbe visualisieren und gleichzeitig einen Farbwechsel zulassen. Gleichzeitig soll das Element aber wie eine Combobox oder ein Button in einem Dialog platziert werden können.

Dazu wird ein JPanel erweitert. Dieser kann eingefärbt werden und in dessen Mitte wird ein Button gesetzt. Sobald er geklickt wird, erscheint der übliche Farbauswahldialog.

Es gäbe andere Varianten, wie etwa drei Spinner für die RGB-Farben. Aber alle müssen selbst zusammengebaut werden. Die vorgestellte Lösung hat den Vorteil der Übersichtlichkeit, denn es geht vor allem um die Events und deren Behandlung.

Ein eigenes Event

Wenn die Anwendung das Kontrollelement setzt, will sie informiert werden, dass der Benutzer die Farbe gewechselt hat. Dass er den Button geklickt hat, im Chooser nach einer Farbe sucht und dann abbricht, interessiert die Anwendung nicht. Nur ein erfolgter Wechsel der Farbe soll ein Event auslösen. Sinnvollerweise sollte dies auch gleich die Farbe übermitteln, die ausgewählt wurde.

Dazu definiert das Programm ein eigenes Event FarbWechselEvent, das das EventObject von java.util erweitert.

Der Konstuktor nimmt das auslösende Objekt auf und die Farbe, die gewählt wurde. Die Funktion getFarbe wird definiert, um diese zu erhalten.

Die Listenerverwaltung

Der eigene EventListener stellt sich zunächst in einem Interface dar, das das Interface EventListener um die eigene Methode erweitert. Hier lautet sie farbeWechselt und hat als Paramter das eben definierte Event.

Das Interface muss allerdings auch implementiert werden. Diese Implementierung stellt einen Verwalter der Eventlistener dar. Der Verwalter implementiert die selbstdefinierte Methode farbeWechselt, um alle angemeldeten Listener aufzurufen.

Damit der Verwalter alle Listener kennenlernen kann, muss er die vom Interface EventListener vorgeschriebene Methode add implementieren, die die Anmeldung eines Listeners durchführt. Umgesetzt wird dies hier durch eine ArrayList.

Auslösen des Events

In der Ereignisbehandlung des Buttons wird der JColorChooser gestartet. Ist dessen Rückgabewert ungleich null, hat der Benutzer eine neue Farbe gewählt. Nun ist es Zeit, das Event auszulösen. Dazu wird die Methode farbeWechselt des Listenerverwalters aufgerufen, der wiederum die Methode alle Listener aufruft.

Anmelden als Listener

Das CustumControll definiert eine Methode addFarbWahlListener, die als Parameter einen FarbWechselListener erwartet. Dieser wird über die Methode add an den Ereignisverwalter übergeben.

Damit sich die Anwendungsfunktion über addFarbWahlListener anmelden kann, muss sie einen FarbWechselListener und vor allem dessen Methode farbeWechselt implementieren, die schließlich vom Ereignisverwalter im Eventfalle aufgerufen wird.

Hier das komplette Demo-Programm:

import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.EventListener;
import java.util.EventObject;
import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

@SuppressWarnings("serial")
public class CustomColorControl extends JFrame {

    // Wir definieren unser eigenes Event. Es enthält die Farbe
    public class FarbWechselEvent extends EventObject {
        protected Color col = null;

        public FarbWechselEvent(Object source, Color col) {
            super(source);
            this.col = col;
        }

        public Color getFarbe() {
            return col;
        }
    }

    // Welche Funktionen muss ein Listener implementieren?
    public interface FarbWechselListener extends EventListener {
        void farbeWechselt(FarbWechselEvent e);
    }

    // Die Liste der Listener verwalten
    public class FarbWechselVerteiler implements FarbWechselListener {
        // Die Listener werden in einer Liste gespeichert
        ArrayList listenerliste = new ArrayList();

        @Override
        public void farbeWechselt(FarbWechselEvent e) {
            // rufe die angemeldeten Bearbeiter
            for (FarbWechselListener listener : listenerliste) {
                listener.farbeWechselt(new FarbWechselEvent(e, e.getFarbe()));
            }
        }

        public void add(FarbWechselListener listener) {
            // Melde neuen Listener an.
            this.listenerliste.add(listener);
        }
    }

    public class CustomColorPanel extends JPanel {
        JButton farbButton = new JButton();
        private JPanel farbFlaeche = new JPanel();
        Color aktFarbe = null; // Das Controll hält seine Farbe hier
        FarbWechselVerteiler ereignisVerteiler = new FarbWechselVerteiler();

        public CustomColorPanel(Color parFarbe) {
            aktFarbe = parFarbe; // sichere die Farbe
            // die Fläche stellt die Farbe dar...
            farbFlaeche.setBackground(aktFarbe);
            add(farbFlaeche);
            // und nimmt den Button auf
            farbButton.setText("Farbe wechseln");
            farbFlaeche.add(farbButton);
            // Der Klick auf den Button startet den ColorChooser
            farbButton.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    Color wahlFarbe = JColorChooser.showDialog(null, "Farbwahl", aktFarbe);
                    if (wahlFarbe != null) { // Farbe ist gewählt!
                        setFarbe(wahlFarbe); // speichern und färben
                        // Informiere die Listener!
                        ereignisVerteiler.farbeWechselt(
                                new FarbWechselEvent(
                                        this, wahlFarbe));
                    }
                }
            });
        }

        // Hier melden sich Listener für das Ereignis an
        public void addFarbWahlListener(FarbWechselListener listener) {
            ereignisVerteiler.add(listener);
        }

        public void setFarbe(Color col) {
            aktFarbe = col;
            farbFlaeche.setBackground(aktFarbe);
        }

    }

    public CustomColorControl() {
        super("CustomColorControl");
        setLayout(new GridLayout(2,1));
        JLabel label = new JLabel("neue Farbe");
        add(label);
        // erzeuge das neue Control
        CustomColorPanel control = new CustomColorPanel(new Color(226,0,116));
        add(control);
        // melde es für das Event an
        control.addFarbWahlListener(new FarbWechselListener() {

            @Override
            public void farbeWechselt(FarbWechselEvent e) {
                label.setText(""+e.getFarbe().toString()); // hole die Farbe
            }
            
        });
        pack();
        setVisible(true);
    }
    
    public static void main(String[] args) {
        new CustomColorControl();
    }

}