Obsługa zdarzeń
Transkrypt
Obsługa zdarzeń
Obsługa zdarzeń Tomasz Borzyszkowski Podstawy Sposób obsługi zdarzeń przez pierwszą wersję Javy 1.0 znacznie się różni od sposobu obsługi zdarzeń w nowych wersjach Javy, zaczynając od wersji 1.1. Metoda obsługi zdarzeń Javy 1.0 jest wciąż wspierana, lecz nie zalecana w nowych implementacjach. W trakcie wykładu przedstawimy nowy model zdarzeń. Koncepcja nowego modelu zdarzeń jest prosta: obiekt źródłowy generuje zdarzenie i przesyła je do jednego lub wielu obiektów nasłuchujących. W tym schemacie obiekt nasłuchujący po prostu czeka, aż otrzyma zdarzenie. Po otrzymaniu zdarzenia obiekt nasłuchujący obsługuje zdarzenie i po zakończeniu czeka na kolejne zdarzenie. W modelu tym logika związana z przetwarzaniem zdarzeń jest oddzielona od logiki interfejsu użytkownika, która generuje te zdarzenia. Często mówi się, że element interfejsu użytkownika deleguje przetwarzanie zdarzenia do oddzielnej części kodu. 2 Zdarzenia W starym modelu zdarzeń, zdarzenie było propagowane do całej hierarchii obiektów składającej się na aplikację, do momentu obsłużenia przez jakiś komponent aplikacji. Takie podejście zmuszało obiekty do odbierania zdarzeń, których nie potrafiły obsłużyć. Powodowało to znaczne straty czasowe związane z przesyłaniem zdarzeń. Model delegacyjny eliminuje tę wadę – obiekty nasłuchujące rejestrują typy zdarzeń, które mogą obsłużyć i tylko takie są do nich wysyłane. W modelu delegacyjnym, zdarzenie jest obiektem, który opisuje stan zmian zachodzących w obiekcie źródłowym. Zdarzenie takie może być wygenerowane wskutek interakcji człowieka z aplikacją (naciśnięcie przycisku, wypełnienie pola tekstowego, wybranie pozycji z listy, ...). Istnieją także zdarzenia, które nie są generowane przez użytkownika. Zdarzenia takie mogą pochodzić od innych obiektów współdziałających z interfejsem użytkownika (przekroczenie czasu, osiągnięcie wartości krytycznej, ...). 3 Zdarzenia źródła Źródłem zdarzenia nazywamy obiekt generujący zdarzenie, jako odpowiedź na zmianę jego stanu wewnętrznego. Źródła mogą generować więcej niż jeden typ zdarzenia. Muszą natomiast zarejestrować odpowiednie obiekty nasłuchujące, by mogły one otrzymywać i obsługiwać zdarzenia generowane w źródle. Każdy typ zdarzenia posiada swoją specyficzną metodę rejestracji: public void addTypListener(TypListener el) Typ jest nazwą zdarzenia, el jest referencją do odpowiedniego obiektu nasłuchującego. Np. metoda rejestrująca zdarzenia związane z klawiaturą nazywa się addKeyListener(). W przypadku zajścia zdarzenia wszystkie obiekty nasłuchujące zarejestrowane do danego typu zdarzenia otrzymują kopię tego zdarzenia. Obiekt źródłowy udostępnia obiektowi nasłuchującemu metodę wyrejestrowania nasłuchu danego typu zdarzenia. Służy do tego metoda: public void removeTypListener(TypListener el)4 Zdarzenia schemat Obiekt słuchacza, potomek EventObject, przyporządkowujemy obiektowi źródła następująco: obiektŹródłaZdarzenia .addTypListener(obiektSłuchacza) Od tej chwili obiektSłuchacza będzie otrzymywał informacje o wszystkich zdarzeniach danego Typu pochodzących od danego obiektu będącego źródłem zdarzenia. Klasa obiektu słuchacza powinna implementować odpowiedni interfejs, zależny od typu zdarzenia. Np. dla typu action event powinniśmy implementować interfejs ActionListener, a klasa słuchacza musi implementować metodę actionPerformed. class MojSluchacz implements ActionListener { public void actionPerformed(ActionEvent zdarzenie){ // tu kod obsługi zdarzenia } Zobacz:TestPrzyciskow{1,2}.java } 5 Wygląd i wrażenie Wygląd i wrażenie to predefiniowany w Swingu wygląd poszczególnych komponetów okna. Domyślnym wyglądem programów w Swing jest Metal. Wygląd programu można zmieniać na dwa sposoby: w katalogu jdk/jre/lib należy utworzyć plik swing.properties, w którym zmieniamy wartość pola swing.defaultlaf na nazwę nowego wyglądu: swing.defaultlaf=javax.swing.plaf.motif.MotifLookAndFeel w programie użyć metody statycznej UIManager.setLookAndFeel, podając nazwę wybranego wyglądu, następnie wywołujemy metodę SwingUtilities.updateComponentTreeUI, aby odświerzyć wszystkie komponenty. Wystarczy jej podać tylko jeden komponent – metoda sama znajdzie resztę. Zobacz:TestWygladu.java 6 Typy zdarzeń Zdarzenia semantyczne: ActionEvent: kliknięcie przycisku, wybór elementu z menu, z listy, naciśnięcie ENTER w polu tekstowym AdjustmentEvent: przesuwanie suwaka ItemEvent: wybór jednego z pól wyboru lub elementów z listy TextEvent: zmiana zawartości pola tekstowego Zdarzenia niskiego poziomu: ComponentEvent: komponent został przesunięty, wyświetlony, ukryty, lub został zmieniony jego rozmiar KeyEvent: naciśnięcie lub zwolnienie klawisza MouseEvent: naciśnięcie lub zwolnienie klawisza myszki, lub przesunięcie kursora myszki FocusEvent: Komponent został uaktywniony lub dezaktywowany WindowEvent: okno zostało uaktywnione, zminimalizowane lub zamknięte ContainerEvent: komponent został dadany lub usuniety z 7 pojemnika graficznego Klasa KeyEvent Zobacz: Szkic.java Zdarzenie tego typu jest generowane, gdy nastąpiło odczytanie wejścia z klawiatury. Istnieją trzy typy zdarzeń tej klasy: KEY_PRESSED KEY_RELEASED KEY_TYPED Dwa pierwsze są generowane, gdy naciśniemy dowolny klawisz. Trzecie, gdy w wyniku naciśnięcia klawisza wygenerowany zostanie znak. Klasa definiuje stałe mapujące poszczególne znaki, np. stałe od VK_A do VK_Z, itd. Konstruktor (przykład): KeyEvent(Component src, int type, long when, int modifiers, int code, char ch) gdzie when jest czasem systemowym zajścia zdarzenia, code jest kodem naciśniętego klawisza, np. VK_SHIFT lub VK_A, ch jest wygenerowanym znakiem lub stałą CHAR_UNDEFINED, gdy znak nie jest generowany. Metoda getKeyCode() oddaje kod znaku, natomiast getKeyChar() wygenerowany znak. 8 Klasa MouseEvent Zobacz: TestMyszki.java Zdarzenie tego typu jest generowane przez przesuwanie lub klikanie myszą w interfejsie użytkownika. Dostępne są następujące typy: MOUSE_CLICKED MOUSE_DRAGGED MOUSE_ENTERED MOUSE_EXITED MOUSE_MOVED MOUSE_PRESSED MOUSE_RELEASED Konstruktor: MouseEvent(Component src, int type, long when, int modifiers, int x, int y, int clicks, boolean triggersPopup) gdzie x i y są współrzędnymi kursora myszy, clicks jest liczbą kliknięć, triggersPopup jest true, gdy zdarzenie spowodowało otworzenie menu, false w przeciwnym przypadku. Najczęściej używanymi metodami są: getX(), getY(), getPoint(), translatePoint(addToX, addToY), getClickCount() i isPopupTrigger(). 9