Zielony Smok - logo witryny

Generowanie własnych zdarzeń dziedziczących po AWTEvent

Ten sposób dziedziczenia jest możliwy do zastosowania, kiedy tworzony przez nas obiekt jest komponentem Javy. Tutaj jest to klasa dziedzicząca po JComponent.

Tworzymy klasę zdarzenia SmokEvent.

Klasa SMokEvent
package events1;
import java.awt.*;
class SmokEvent extends AWTEvent {
    private static final long serialVersionUID = 1126508309980726325L;
    //nr porzadkowy zdarzenia nie moze byc mniejszy niz L (mniejsze niz L
    //sa zarezerwowane dla jezyka Java)
    private static final int L = AWTEvent.RESERVED_ID_MAX;
    public static final int SMOK_ZASNAL = L + 1;
    public static final int SMOK_OBUDZIL_SIE = L + 2;
    //Tworzy nowe zdarzenie
    //podaje sie obiekt na ktorym zachodzi zdarzenie i identyfikator
    //zdarzenia (ktorys z powyzszych);
    public SmokEvent(Smok s, int id) {
        super(s, id);
    }
}

Tworzymy dwa zdarzenia. Każde ze zdarzeń musi mieć inny numer, który jest większy od stałej AWTEvent.RESERVED_ID_MAX.
Nazwa stałej do której przyporządkowano numer jest nazwą zdarzenia.

Konstruktor zdarzenia tworzy obiekt zdarzenia dla podanej klasy (Smok) i z podanym numerem
zdarzenia, który jest jednym z powyższych numerów. Ten numer jednoznacznie identyfikuje zdarzenie.

Aby móc zarejestrować zdarzenie musimy napisać klasę słuchacza zdarzenia. Napisaliśmy interfejs SmokListener.

Klasa SmokLstener
package events1;
import java.util.*;
//Nowy listener z dwiema metodami
//implementacja listenera jest podana w klasie Main
interface SmokListener extends EventListener {
    void smokZasnal(SmokEvent event);
    void smokObudzilSie(SmokEvent event);
}

SmokListener dziedziczy po klasie EventListener. Określa dwie metody:
smokZasnal() i smok ObudziłSie() przyjmujące jako argument obiekt klasy
SmokEvent.

Żeby móc generować zdarzenia i nasłuchiwać tych zdarzeń musimy napisać stosowną klasę. Napisaliśmy klasę Smok.

Klasa Smok
package events1;
import java.awt.*;
import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
class Smok extends JComponent {
    private static final long serialVersionUID = 6520666450916057531L;
    //listenerList jest dziedziczona z klasy JComponent
    public Smok() {
        listenerList = new EventListenerList();
    }
    //dodaje listener do listy listenerow
    public void addSmokListener(SmokListener listener) {
        listenerList.add(SmokListener.class, listener);
    }
    //usuwa listener z listy listenerow
    public void removeListener(SmokListener listener) {
        listenerList.remove(SmokListener.class, listener);
    }
    //przetwarza kolejke zdarzen
    @Override
    public void processEvent(AWTEvent event) {
        if (event instanceof SmokEvent) {
            processSmokEvent((SmokEvent) event);//jesli SmokEvent
        } else {
            super.processEvent(event);//kazde inne zdarzenie
        }
    }
    private void processSmokEvent(SmokEvent event) {
        //tworzy tablice zdarzen nalezacych do klasy SmokListener
        EventListener[] sluchacze = listenerList
                .getListeners(SmokListener.class);
        int id = event.getID();
        //wywoluje odpowiednia metode w listenerze w zaleznosci
        //od tego ktore zdarzenie zaszlo
        for (EventListener aSluchacze : sluchacze) {
            switch (id) {
                case SmokEvent.SMOK_ZASNAL:
                    ((SmokListener) aSluchacze).smokZasnal(event);
                    break;
                case SmokEvent.SMOK_OBUDZIL_SIE:
                    ((SmokListener) aSluchacze).smokObudzilSie(event);
                    break;
            }
        }
    }
    //metoda wpisujaca zdarzenie SmokEvent do kolejki zdarzen
    //mozna to tez zrobic bez metody powielajac te dwie linijki
    //kodu
    public void uspijSmoka() {
        SmokEvent event = new SmokEvent(this, SmokEvent.SMOK_ZASNAL);
        EventQueue kolejka = Toolkit.getDefaultToolkit().getSystemEventQueue();
        kolejka.postEvent(event);
    }
    //j.w.
    public void obudzSmoka() {
        SmokEvent event = new SmokEvent(this, SmokEvent.SMOK_OBUDZIL_SIE);
        EventQueue kolejka = Toolkit.getDefaultToolkit().getSystemEventQueue();
        kolejka.postEvent(event);
    }
}

Należy zwrócić uwagę, że klasa Smok dziedziczy po klasie JComponent, dzięki czemu dziedziczy po tej klasie obiekt listenerList, czyli listę listenerów. Tworzymy nowy obiekt dla naszego smoka.

Następnie dodajemy metody dodające nasz listener SmokListener do listy listenerów oraz usuwające nasz listener smokListener z listy listenerów.

Następnie przesłaniamy metodę processEvent przetwarzającą zdarzenia. Mogą zajść dwa przypadki. Albo zdarzenie jest klasy SmokEvent i wtedy należy uruchomić metodę processSmokEvent albo jest to zdarzenie innej klasy i wtedy wywołaj metodę processEvent klasy rodzicielskiej (JComponent).

Metoda processSmokEvent() tworzy tablicę słuchaczy należących do klasy SmokListener, sprawdza identyfikator zdarzenia, a następnie wywołuje odpowiednią metodę listenera SmokListener, w zależności od tego, które zdarzenie zaszło.

Następnie tworzymy metodę uspijSmoka() generującą zdarzenie SMOK_ZASNAL. Metoda pobiera kolejkę zdarzeń, dodaje do niej generowane zdarzenie.

Podobnie działa metoda obudzSmoka() generująca zdarzenie SMOK_OBUDZIL_SIE.

Skoro już mamy klasę Smok, przywołujemy do życia obiekt Smok.

Zrobiliśmy to w klasie Main.

Klasa Main
package events1;
class Main {
    //Implementacja obu metod listenera
    public static void main(String[] args) {
        Smok smok = new Smok();
        smok.addSmokListener(new SmokListener() {
            @Override
            public void smokObudzilSie(SmokEvent event) {
                System.out.println("Smok obudził się");
            }
            @Override
            public void smokZasnal(SmokEvent event) {
                System.out.println("Smok zasnął");
            }
        });
        smok.uspijSmoka();
        smok.obudzSmoka();
    }
}

Tworzymy obiekt Smok. Dodajemy listener określający co zrobić jeśli zajdzie odpowiednie zdarzenie. Musimy zaimplementować obie metody listenera. Następnie generujemy oba zdarzenia po kolei.

Aby zdarzenie mogło być wykonywane cyklicznie to klasa Smok musi implementować Runnable lub dziedziczyć po klasie Thread.

Po uruchomieniu otrzymujemy na konsoli:

Smok zasnął
Smok obudził się