13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 1
13. Swing - obsługa zdarze
ń
13.1 Przykłady
13.2 Zasady
13.3 Typy zdarze
ń
13.4 Implementowanie obsługi zdarze
ń
13.5
Action
,
Abstract Action
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 2
13.1 Przykłady obsługi zdarze
ń
Przykład 13.1
. Aplet zawiera GUI w postaci pojedynczego przycisku
wydaj
ą
cego d
ź
wi
ę
k dzwonka po klikni
ę
ciu mysz
ą
w przycisk.
Fragment kodu obsługi zdarze
ń
dla przycisku:
public class Beeper ... implements ActionListener {
...
// w miejscu inicjalizacji:
button.addActionListener(this);
...
public void actionPerformed(ActionEvent e) {
...// Spowoduj dźwięk dzwonka...
Toolkit.getDefaultToolkit().beep();
}
}
Komentarz:
1) Klasa u
ż
ytkownika
Beeper
implementuje interfejs
ActionListener
– jej
jedyn
ą
metod
ę
actionPerformed
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 3
2) Obiekt klasy
Beeper
mo
ż
e si
ę
zarejestrowa
ć
dla obsługi zdarze
ń
akcji
zgłaszanych przez przycisk – stosujemy w tym celu metod
ę
klasy
Button
addActionListener
.
3) Teraz metoda klasy
Beeper
-
actionPerformed
– jest wywoływana do
obsługi zdarzenia przycisku.
W
jednym programie
mo
ż
e zosta
ć
zarejestrowana
dowolna liczba
obiektów
dla obsługi ró
ż
nych zdarze
ń
zgłaszanych przez dowoln
ą
liczb
ę
obiektów.
Program mo
ż
e posiada
ć
po jednej obsłudze
dla ka
ż
dego zdarzenia (a
nawet
wi
ę
cej ni
ż
jedn
ą
obsług
ę
jednego zdarzenia).
Z drugiej strony program mógłby posiada
ć
jedn
ą
obsług
ę
wspóln
ą
dla
wszystkich zdarze
ń
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 4
Przykład 13.2.
Aplet zawiera dwa
ź
ródła zdarze
ń
(obiekty klasy
JButton
) i dwa obiekty
obsługi zdarze
ń
. Pierwszy obiekt (pewnej klasy
MultiListener
) obsługuje
zdarzenia obu przycisków – obsługa polega na dodaniu tekstu – etykiety
przycisku - w górnym obszarze przycisku. Drugi obiekt (pewnej klasy
Eavesdropper
) obsługuje jedynie zdarzenia jednego przycisku – dodaje
tekst – etykiet
ę
przycisku - w dolnym polu tekstowym.
Fragment kodu obsługi zdarze
ń
dla przycisku:
public class MultiListener ... implements ActionListener {
...
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 5
// W miejscu inicjalizacji:
button1.addActionListener(this);
// Pierwszy obiekt obsługujący
button2.addActionListener(this);
// Drugi obiekt obsługujący zdarzenie
button2.addActionListener(new Eavesdropper(bottomTextArea));
}
public void actionPerformed(ActionEvent e) {
topTextArea.append(e.getActionCommand() + newline);
}
}
class Eavesdropper implements ActionListener {
...
public void actionPerformed(ActionEvent e) {
myTextArea.append(e.getActionCommand() + newline);
}
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 6
Przykład 13.3
Kolejny aplet ilustruje obsług
ę
zdarzenia innego typu ni
ż
zdarzenia typu
akcji – zdarzenia od myszy - click, press, release, enter, exit.
Obsługa zdarzenia polega na wy
ś
wietleniu w polu tekstowym napisu
odpowiadaj
ą
cego rodzajowi zdarzenia, które zaszło nad prostok
ą
tnym
obszarem.
Fragment kodu obsługi zdarze
ń
:
public class MouseEventDemo ... implements MouseListener {
...
// W miejscu inicjalizacji:
// Rejestracja dla zdarzeń myszy dla obszaru blankArea i apletu:
blankArea.addMouseListener(this);
addMouseListener(this);
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 7
}
public void mousePressed(MouseEvent e) {
saySomething("Mouse pressed; # of clicks: "
+ e.getClickCount(), e);
}
public void mouseReleased(MouseEvent e) {
saySomething("Mouse released; # of clicks: "
+ e.getClickCount(), e);
}
public void mouseEntered(MouseEvent e) {
saySomething("Mouse entered", e);
}
public void mouseExited(MouseEvent e) {
saySomething("Mouse exited", e);
}
public void mouseClicked(MouseEvent e) {
saySomething("Mouse clicked (# of clicks: "
+ e.getClickCount() + ")", e);
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 8
void saySomething(String eventDescription, MouseEvent e) {
textArea.append(eventDescription + " detected on "
+ e.getComponent().getClass().getName()
+ "." + newline);
}
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 9
13.2 Zasady tworzenia obsługi zdarze
ń
Przypomnijmy,
ż
e obsługa zdarze
ń
i malowanie GUI wykonywane s
ą
przez jeden ten sam w
ą
tek.
1) Obiekty generuj
ą
ce zdarzenia
Ka
ż
da metoda obsługi zdarzenia posiada jeden
argument.
Jest nim
obiekt klasy pochodnej od
EventObject
. Np. dla klas zdarze
ń
myszy
istnieje klasa
MouseEvent
.
Metoda klasy
EventObject
:
Object getSource()
zwraca obiekt, który zgłosił zdarzenie.
Inne klasy argumentów obsługi zdarze
ń
te
ż
posiadaj
ą
metody
zwracaj
ą
ce obiekt, w którym wystapiło zdarzenie, ale o specyficznym
typie wyniku. Np. w klasie
ComponentEvent
istnieje metoda:
Component getComponent
()
,
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 10
która zwraca komponent a nie generalny obiekt.
Metoda obsługi zdarzenia zwykle pobiera informacje o zdarzeniu od
swojego argumentu - obiektu klasy zdarzeniowej. Np. obiekt klasy
MouseEvent
posiada dane o tym, ile było klikni
ęć
, jakie klawisze myszy
zostały wybrane itd.
2) Zdarzenia nisko-poziomowe a zdarzenia semantyczne
Zdarzenia niskiego poziomu
reprezentuj
ą
zjawiska generowane przez
system zarz
ą
dzania oknami lub wprowadzanie danych. S
ą
nimi:
•
zdarzenia myszy lub klawiatury
(s
ą
bezpo
ś
rednio wynikiem
wprowadzania danych przez u
ż
ytkownika),
•
zdarzenia
komponentu
(nadzorowanie
pozycji,
rozmiaru,
widoczno
ś
ci),
•
zdarzenia kontenera
(gdy dodawany/usuwany jest komponent),
•
uzyskiwanie/utrata kontekstu
klawiatury przez komponent,
•
zdarzenia okna
(nadzoruj
ą
stan okna dla komponentu).
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 11
Pozostałe zjawiska generuj
ą
zdarzenia semantyczne. S
ą
nimi
zdarzenia typu:
•
“
action
event”,
•
“
item
event”,
•
“
list selection
event”.
Sposób wywołania semantycznego zdarzenia zale
ż
y od komponentu.
Np. przycisk zgłasza “action event”, gdy u
ż
ytkownik klika w niego, a pole
tekstowe zgłasza “action event”, gdy u
ż
ytkownik wciska klawisz Return.
Zdarzenie te zale
żą
równie
ż
od
ś
rodowiska “look and feel”.
Preferowa
ć
nale
ż
y obsług
ę
zdarze
ń
semantycznych, gdy
ż
kod obsługi
b
ę
dzie ogólniejszy i przenaszalny.
Np. obsługa “action events” dla przycisku zapewni reakcj
ę
zarówno
wtedy, gdy przycisk wybierany jest mysz
ą
lub klawiatur
ą
, podczas gdy
obsługa zdarze
ń
myszy dla przycisku nie uwzgl
ę
dni klawiatury.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 12
3) Adaptery i klasy wewn
ę
trzne w obsłudze zdarze
ń
Wi
ę
kszo
ść
interfejsów deklaruje wi
ę
cej ni
ż
jedn
ą
metod
ę
. Np.
MouseListener
deklaruje 5 metod:
mousePressed,
mouseReleased,
mouseEntered,
mouseExited,
mouseClicked
.
Nawet wtedy, gdy nie obsługujemy niektórych zdarze
ń
myszy musimy
zaimplementowa
ć
wszystkie metody implementowanego interfejsu.
Przykład 13.4.a
// Przykład kodu o niskiej czytelno
ś
ci:
public class MojaKlasa implements MouseListener {
...
mojObiekt.addMouseListener(this);
...
/* Pusta definicja metody */
public void mousePressed(MouseEvent e) {
}
/* Pusta definicja metody */
public void mouseReleased(MouseEvent e) {
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 13
}
/* Pusta definicja metody */
public void mouseEntered(MouseEvent e) {
}
/* Pusta definicja metody */
public void mouseExited(MouseEvent e) {
}
public void mouseClicked(MouseEvent e) {
...// Implementacja obsługi zdarzenia...
}
}
Istnienie wielu pustych definicji metod zmniejsza czytelno
ść
kodu.
Mo
ż
na zastosowa
ć
adaptery klas
z API, implementuj
ą
ce interfejsy o
wi
ę
cej ni
ż
jednej metodzie. Zawieraj
ą
one metody o
pustym kodzie
.
Np. klasa
MouseAdapter
implementuje interfejs
MouseListener
.
Korzystanie z klasy adapteru
polega na dziedziczeniu z niej.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 14
Przykład
13.4.b
Dziedziczenie
z
klasy
adapteru
zamiast
implementowania interfejsu. Definiujemy tylko 1 metod
ę
interfejsu.
public class MojaKlasa extends MouseAdapter {
...
mojObiekt.addMouseListener(this);
...
public void mouseClicked(MouseEvent e) {
...// Obsługa zdarzenia w tym miejscu...
}
}
W przypadku
apletów
klasa u
ż
ytkownika musi dziedziczy
ć
z bazowej
klasy apletu a nie z adapteru interfejsu. W takiej sytuacji mo
ż
na
skorzysta
ć
z
klasy wewn
ę
trznej
, która dziedziczy po klasie adapteru, np.
po
MouseAdapter
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 15
Przykład 13.4.c
Klasa wewn
ę
trzna
dziedziczy z klasy adapteru.
public class MojaKlasa extends Applet {
...
mojObiekt.addMouseListener(new MyAdapter());
...
class MyAdapter extends MouseAdapter {
public void mouseClicked(MouseEvent e) {
...// Tu podamy kod obsługi zdarzenia ...
}
}
}
Przykład 13.4.d
Korzystanie z
anonimowej klasy wewn
ę
trznej
.
public class MojaKlasa extends Applet {
...
mojObiekt.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
...// Tu podamy kod obsługi zdarzenia ...
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 16
}
});
...
}
}
Klasa wewn
ę
trzna (o ile nie jest statyczna) mo
ż
e korzysta
ć
nawet z
prywatnych pól i metod klasy obejmuj
ą
cej. Do obiektu obejmuj
ą
cego
mo
ż
na odwoła
ć
si
ę
przez:
klasaObejmująca.this .
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 17
13.3 Typy zdarze
ń
dla komponentów Swing
Typy zdarze
ń
generowanych przez dany komponent wynikaj
ą
z typów
“event listeners” u których mo
ż
na zarejestrowa
ć
swoje obiekty obsługi.
Np. klasa
Component
definiuje nast
ę
puj
ą
ce metody rejestracji obiektów:
addComponentListener ,
addFocusListener ,
addKeyListener ,
addMouseListener ,
addMouseMotionListener .
Konkretny komponent generuje tylko te zdarzenia, dla których istniej
ą
rejestracje obiektów obsługi zdarze
ń
.
1) Typy zdarze
ń
wyst
ę
puj
ą
ce we wszystkich komponentach Swinga
Komponenty
Swing
-a dziedzicz
ą
z
klasy
Component
w AWT
, dlatego te
ż
wyst
ę
puj
ą
w nich zdarzenia poni
ż
szych 5 typów:
component listener, focus listener,
key listener, mouse events, mouse-motion events .
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 18
Wszystkie komponenty
Swing-a
dziedzicz
ą
te
ż
z klasy
Container
w AWT
,
chocia
ż
wi
ę
kszo
ść
z nich nie pełni roli kontenera. Ale ka
ż
dy komponent
Swing-a mo
ż
e (teoretycznie) generowa
ć
zdarzenia
typowe dla
kontenera
, tzn. zdarzenia powiadamiaj
ą
ce o dodaniu lub usuni
ę
ciu
komponentu do/z kontenera.
W praktyce tylko
kontenery
(takie jak panele i ramki) i
komponenty
zło
ż
one
(jak lista wysuwnych opcji) generuj
ą
zdarzenia dla kontenera.
Klasa
JComponent
posiada dalsze trzy typy obsługi zdarze
ń
:
“
AncestorListener
” – obiekt obsługi jest powiadamiany, gdy dodawani
lub usuwani s
ą
z hierarchii zawarto
ś
ci przodkowie komponentu, a
tak
ż
e gdy staj
ą
si
ę
oni widoczni, s
ą
ukrywani lub przesuwani.
“
PropertyChangeListener
” – obiekt obsługi jest powiadamiany o
zmianach w ustawionych na trwałe własno
ś
ciach komponentu (tzw.
„bound properties”).
“
VetoableChangeListener
” – obiekt obsługi jest powiadamiany o
zmianach własno
ś
ci o zadanych ograniczeniach.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 19
2) Inne typy obsługi zdarze
ń
w komponentach Swinga
ActionListener
ChangeListener
CaretListener
DocumentListener
UndoableEditListener
ItemListener
WindowListener
ListSelection
i szereg indywidualnych.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 20
13.4 Implementowanie obsługi wybranych zdarze
ń
1) Zdarzenia akcji (Action Listener)
Zdarzenie typu “action event” powstanie np. wtedy, gdy u
ż
ytkownik w UI
kliknie przycisk, wybierze opcj
ę
menu lub przyci
ś
nie klawisz
Return
dla
pola
tekstowego.
W
jego
wyniku
do
wszystkich
obiektów
zarejestrowanych na wła
ś
ciwym komponencie zostanie rozesłane
wywołanie metody
actionPerformed
.
Interfejs
ActionListener
posiada tylko jedn
ą
metod
ę
:
void actionPerformed(ActionEvent)
Parametrem metody
jest obiekt klasy
ActionEvent
. W tej klasie
zdefiniowano m.in. dwie po
ż
yteczne metody:
String getActionCommand()
Metoda zwraca napis rozkazu zwi
ą
zany z akcj
ą
. Wi
ę
kszo
ść
klas, których
obiekty mog
ą
generowa
ć
zdarzenie typu akcji posiada metod
ę
setActionCommand
umo
ż
liwiaj
ą
c
ą
ustalenie tego napisu rozkazu.
Je
ś
li ten napis nie jest ustalony to rozkaz zwi
ą
zany z akcj
ą
jest tekstem
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 21
wy
ś
wietlanym w komponencie.
Jesli obiekt posiada wiele obiektów opcji, czyli wiele mo
ż
liwych akcji,
które mog
ą
zosta
ć
wykonane, to zwykle napis rozkazu odpowiada
nazwie wybranej opcji.
int getModifiers()
Metoda zwraca warto
ść
całkowit
ą
okre
ś
laj
ą
c
ą
jaki klawisz specjalny
został przyci
ś
ni
ę
ty przez u
ż
ytkownika podczas generacji zdarzenia typu
akcja. Mo
ż
liwy wynik to stałe zdefiniowane w
ActionEvent:
SHIFT_MASK, CTRL_MASK, META_MASK, ALT_MASK
.
Np.
gdy u
ż
ytkownik skorzystał z przycisku
Shift
dla wyboru opcji to poni
ż
sze
wyra
ż
enie b
ę
dzie prawdziwe:
actionEvent.getModifiers() & ActionEvent.SHIFT_MASK
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 22
2) Zdarzenia zmiany stanu (Change Listener)
Zdarzenie typu “zmiana” wyst
ą
pi wtedy, gdy
dany komponent zmienia
stan
.
Np.
•
Przycisk
generuje takie zdarzenie za ka
ż
dym razem gdy zostanie
przyci
ś
ni
ę
ty. Domy
ś
lna obsługa tego zdarzenia dla przycisku jest
zapewniona przez
ś
rodowisko „look-and-feel” (np. od
ś
wie
ż
enie
wygl
ą
du).
•
Zdarzenie typu “zmiana” umo
ż
liwia podstawow
ą
funkcjonalno
ść
dwóch
komponentów Swinga:
suwaka
i „
wyboru kolorów
”. Zdarzenie
generowane jest wtedy, gdy zmienia sie warto
ś
c suwaka wzgl. gdy
u
ż
ytkownik wybiera nowy kolor.
Przykład 13.5
. Obsługa zdarzenia typu “zmiana” dla suwaka.
//...w miejscu inicjalizacji
framesPerSecond.addChangeListener(new SliderListener());
...
class SliderListener implements ChangeListener {
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 23
public void stateChanged(ChangeEvent e) {
JSlider source = (JSlider)e.getSource();
if (!source.getValueIsAdjusting()) {
int fps = (int)source.getValue();
...
}
}
}
Interfejs
ChangeListener
deklaruje tylko jedn
ą
metod
ę
:
void stateChanged(ChangeEvent)
Parametr metody jest typu
ChangeEvent
. Wła
ś
ciw
ą
metod
ą
dla pobrania
komponentu,
który
zgłosił
zdarzenie
jest
metoda
getSource
odziedziczona po klasie
EventObject
.
Klasa
ChangeEvent
nie definiuje dodatkowych metod.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 24
3) Zdarzenia komponentu (Component Listener)
Zdarzenia typu “component event” s
ą
generowane przez komponent
wtedy, gdy zostanie on:
•
ukryty
(metoda obsługi -
componentHidden
)
•
uczyniony widocznym
(metoda obsługi –
componentShown
),
•
przesuni
ę
ty
(metoda obsługi –
componentMoved
) lub nast
ą
pi
•
zmiana jego rozmiaru
(metod obsługi
componentResized
).
Obsługa tych zdarze
ń
jest potrzebna obiektom, które
zapewniaj
ą
informacj
ę
o komponencie
, ale nie jest potrzebna dla zarz
ą
dzania
widokiem lub dla malowania komponentu.
Zdarzenia generowane przy ukrywaniu lub nadaniu widoczno
ś
ci
komponentowi s
ą
wynikiem wywoła
ń
metody klasy
Component
:
setVisible
(lub metod
show, hide
).
Uwaga:
proces ikonizacji okna nie powoduje zdarzenia ukrycia
komponentu lecz zdarzenia nale
żą
cego do zdarze
ń
okna („window
event”).
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 25
Przykład 13.6.
Aplet
ComponentEventDemo
zawiera przycisk „
Start playing ...”
powoduj
ą
cy
wyswietlenie
okna ramki
(typu
JFrame
). W ramce jest
panel
posiadaj
ą
cy
etykiet
ę
i
pole wyboru
(„checkbox”) nadzoruj
ą
ce widoczno
ść
etykiety.
Dla celów kontrolnych istnieje te
ż
pole tekstowe
wy
ś
wietlaj
ą
ce
komunikaty
dla
ka
ż
dego
zdarzenia
typu
“
component
event
”
wygenerowanego przez
okno, panel, etykiet
ę
lub pole wyboru
.
Fragment GUI apletu zawieraj
ą
cy:
- przycisk „Start playing”,
- pole tekstowe z komunikatami,
- przycisk zerowania pola tekstowego
„Clear”
Opuszczenie
strony apletu
powoduje
ukrycie okna
(
componentHidden
), a
jego ponowne
pojawienie
(
componentShown
) nast
ę
puje po powrocie do
strony apletu.
public class ComponentEventDemo ... implements ComponentListener {
...
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 26
// W miejscu inicjalizacji :
aFrame = new JFrame("A Frame");
ComponentPanel p = new ComponentPanel(this);
aFrame.addComponentListener(this);
p.addComponentListener(this);
...
public void componentHidden(ComponentEvent e) {
displayMessage("componentHidden event from "
+ e.getComponent().getClass().getName());
// Pobiera nazwę klasy
// obiektu zgłaszającego zdarzenie
}
public void componentMoved(ComponentEvent e) {
displayMessage("componentMoved event from "
+ e.getComponent().getClass().getName());
}
public void componentResized(ComponentEvent e) {
displayMessage("componentResized event from "
+ e.getComponent().getClass().getName());
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 27
public void componentShown(ComponentEvent e) {
displayMessage("componentShown event from "
+ e.getComponent().getClass().getName());
}
}
// Koniec definicji klasy głównej
class ComponentPanel extends JPanel ... {
...
ComponentPanel(ComponentEventDemo listener) {
...// Po utworzeniu etykiety i pola wyboru :
label.addComponentListener(listener);
checkbox.addComponentListener(listener);
}
...
}
Interfejs
ComponentListener
i odpowiadaj
ą
ca mu klasa adaptera
ComponentAdapter
deklaruj
ą
cztery metody:
void componentHidden(ComponentEvent)
Metoda wołana po ukryciu komponentu wywołaniem setVisible(false).
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 28
void componentMoved(ComponentEvent)
Metoda wołana po przesuni
ę
ciu komponentu wzgl
ę
dem jego kontenera.
void componentResized(ComponentEvent)
Metoda wołana po zmianie rozmiaru komponentu (prostok
ą
ta
obejmuj
ą
cego go).
void componentShown(ComponentEvent)
Metoda wołana po nadaniu widoczno
ś
ci komponentowi wywołaniem
setVisible(true).
Ka
ż
da z powy
ż
szych metod posiada parametr typu
ComponentEvent
. W
tej klasie zdefiniowano po
ż
yteczn
ą
metod
ę
:
Component getComponent() ,
- zwraca komponent, który wygerenował zdarzenie.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 29
4) Zdarzenia kontenera (Container Listener)
Zdarzenia typu “container events” s
ą
generowane przez kontener zaraz
po tym, jak
dodany
zostanie
do niego komponent
lub komponent
zostanie
z niego
usuni
ę
ty
.
Te zdarzenia słu
żą
jedynie powiadamianiu
a nie maj
ą
wpływu na samo
wykonanie operacji dodania lub usuni
ę
cia komponentu.
Przykład 13.7.
Aplet
ContainerEventDemo
posiada w swoim GUI przyciski o nazwach:
„
Add a button
” i “
Remove a button
”, które umo
ż
liwiaj
ą
dodanie lub
usuni
ę
cie komponentu do/z panelu poło
ż
onego na dole obszaru apletu.
Ka
ż
da taka operacja spowoduje wygenerowanie przez panel zdarzenia
typu „
container event
” i powiadomienie o tym metod obsługi tego
zdarzenia dla panelu
componentAdded()
lub
componentRemoved()
. W
wyniku obsługi wy
ś
wietlany jest w górnej cz
ęś
ci apletu tekst informuj
ą
cy
o zdarzeniu.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 30
public class ContainerEventDemo ... implements ContainerListener ... {
...// W kodzie inicjalizacji :
buttonPanel = new JPanel();
buttonPanel.addContainerListener(this);
...
public void componentAdded(ContainerEvent e) {
displayMessage(" added to ", e);
}
public void componentRemoved(ContainerEvent e) {
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 31
displayMessage(" removed from ", e);
}
void displayMessage(String action, ContainerEvent e) {
display.append(((JButton)e.getChild()).getText()
+ " was"
+ action
// Parametr zawiera nazwę operacji – dodano/usnięto
+ e.getContainer().getClass().getName()
// Pobierz nazwę klasy
// kontenera, który spowodował zdarzenie
+ newline);
}
...
}
Interfejs
ContainerListener
i jego klasa adapteru
ContainerAdapter
deklaruj
ą
dwie metody:
void componentAdded(ContainerEvent)
- metoda wołana po podaniu komponentu do kontenera.
void componentRemoved(ContainerEvent)
- metoda wołana po usuni
ę
ciu komponentu z kontenera.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 32
Parametr obu metod jest typu
ContainerEvent
– w tej klasie
zdefiniowano dwie po
ż
yteczne metody:
Component getChild()
– metoda zwraca komponent, którego dodanie wzgl. usuni
ę
cie
spowodowało generacj
ę
zdarzenia.
Container getContainer()
- metoda zwraca kontener, który zgłosił zdarzenie.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 33
5) Zdarzenia okna (Window Listener)
Zdarzenia typu
zdarzenia okna
(“window events”) generowane s
ą
przez
okna (typu ramka lub dialog) zaraz po tym, jak okno zostanie
otwarte,
zamkni
ę
te
,
zminimalizowane, przywrócone, uczynione aktywnym
lub
nieaktywnym
:
-
Otwarcie okna
oznacza pierwsze namalowanie okna.
-
Zamkni
ę
cie okna
oznacza usuni
ę
cie go z ekranu.
-
Minimalizacja okna
oznacza zast
ą
pienie go mał
ą
ikonk
ą
na pulpicie.
-
Przywrócenie okna
to operacja odwrotna do minimalizacji.
-
Aktywacja okna
oznacza,
ż
e okno lub zawarty w nim komponent mog
ą
przyjmowa
ć
zdarzenia myszy lub klawiatury.
-
Okno
staje sie
nieaktywne,
gdy okno i zawarte w nim komponenty
trac
ą
mo
ż
liwo
ść
przyjmowania zdarze
ń
myszy i klawiatury.
Uwaga
Zdarzenia polegaj
ą
ce na uczynieniu okna
widocznym
(show, visible) lub
na
ukryciu go
(hide) zaliczane s
ą
do typu
zdarze
ń
komponentu
(„component events”).
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 34
Obsługa zdarzenia zamykania okna
Zdarzenie
zamykania okna
(w wyniku operacji
Close
) jest głównym
zdarzeniem zwi
ą
zanym z oknem wymagaj
ą
cym obsługi.
Istnieje
domy
ś
lna obsługa
zdarzenia zamykania okna polegaj
ą
ca jedynie
na
ukryciu go
(uczynieniu go niewidocznym).
Mo
ż
na ustawi
ć
inny predefiniowany sposób obsługi tego zdarzenia
przez
domy
ś
ln
ą
procedur
ę
obsługi zdarze
ń
okna – np. usuni
ę
cie zasobów
okna – stosuj
ą
c metod
ę
klas
JFrame
lub
JDialog
o nazwie
setDefaultCloseOperation
.
Mo
ż
emy te
ż
zaimplementowa
ć
własn
ą
metod
ę
obsługi
tego zdarzenia,
np. w celu zapami
ę
tania danych zwi
ą
zanych z oknem przed jego
usuni
ę
ciem lub zako
ń
czenie programu, gdy ostatnie jego okno zostanie
zamkni
ę
te.
Je
ś
li implementujemy własn
ą
procedur
ę
obsługi zdarzenia zamykania
okna to mo
ż
emy „
wył
ą
czy
ć
” domy
ś
ln
ą
procedur
ę
obsługi wywołuj
ą
c:
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE)
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 35
Obsługa zdarze
ń
minimalizacji i przywracania okna
Cz
ę
stym celem zada
ń
obsługi zdarze
ń
dla okna jest
zatrzymywanie
w
ą
tków
i
zwalnianie zasobów
wtedy, gdy okno
jest minimalizowane
, a
nast
ę
pnie
ponowne ich restartowanie
, gdy okno
jest przywracane
.
Pozwala to unikn
ąć
niepotrzebnego zajmowania procesora lub innych
zasobów przez w
ą
tki. Np. okno zawiera animacj
ę
– po minimalizacji
okna nale
ż
y zatrzyma
ć
w
ą
tek animacji i zwolni
ć
du
ż
e bufory, a po
przywróceniu okna zrestartowa
ć
w
ą
tek po przywróceniu buforów.
Przykład 13.8.
Aplet
WindowEventDemo
posiada w górnej cz
ęś
ci swojego
GUI przycisk otwieraj
ą
cy małe okno. Klasa główna „nasłuchuje” zdarze
ń
generowanych przez to okno i wy
ś
wietla napisy wła
ś
ciwe dla typu
zdarzenia.
Je
ś
li wył
ą
czymy domy
ś
ln
ą
obsług
ę
zdarzenia zamykania okna to
zdarzenie “window closed” nie zajdzie, gdy
ż
nasza obsługa zdarzenia
“window closing” polega jedynie na wywołaniu
setVisible(false)
(ukryciu
okna) zamiast wykonania zwolnienia zasobów obiektu metod
ą
dispose()
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 36
public class WindowEventDemo ... implements WindowListener {
...//w kodzie inicjalizacji:
// Utwórz ale nie wy
ś
wietlaj okna
window = new JFrame("Okno WindowEventDemo");
window.addWindowListener(this);
// Rejestracja obsługi zdarzeń okna
window.getContentPane().add(
new JLabel("Demonstracja zdarzeń okna "), BorderLayout.CENTER);
window.pack();
}
public void windowClosing(WindowEvent e) {
window.setVisible(false);
displayMessage("Window closing", e);
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 37
}
public void windowClosed(WindowEvent e) {
displayMessage("Window closed", e);
}
public void windowOpened(WindowEvent e) {
displayMessage("Window opened", e);
}
public void windowIconified(WindowEvent e) {
displayMessage("Window iconified", e);
}
public void windowDeiconified(WindowEvent e) {
displayMessage("Window deiconified", e);
}
public void windowActivated(WindowEvent e) {
displayMessage("Window activated", e);
}
public void windowDeactivated(WindowEvent e) {
displayMessage("Window deactivated", e);
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 38
void displayMessage(String prefix, WindowEvent e) {
display.append(prefix
+ ": "
+ e.getWindow()
// Pobierz okno, które wygenerowało zdarzenie
+ newline);
}
...
}
Interfejs
WindowListener
i klasa adaptera
WindowAdapter
deklaruj
ą
metody:
void windowOpened(WindowEvent)
– metoda wołana wtedy, gdy nadzorowane okno zostało namalowane po
raz pierwszy.
void windowClosing(WindowEvent)
- metoda wołana po
żą
daniu u
ż
ytkownika aby zamkn
ąć
okno –
procedura obsługi powinna usun
ąć
zasoby okna lub ukry
ć
okno metod
ą
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 39
setVisible(false)
.
void windowClosed(WindowEvent)
– metoda wołana po zamkni
ę
ciu nadzorowanego okna.
void windowIconified(WindowEvent)
void windowDeiconified(WindowEvent)
- metody wołane po minimalizacji
wzgl. przywróceniu nadzorowanego okna.
void windowActivated(WindowEvent)
void windowDeactivated(WindowEvent)
- metody wołane po uczynieniu
aktywnym wzgl. nieaktywnym nadzorowanego okna.
Ka
ż
da z powy
ż
szych metod posiada parametr typu
WindowEvent
.
Metoda
Window getWindow()
- pobiera i zwraca okno, które wygenerowało to zdarzenie.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 40
6) Zdarzenia wewn
ę
trznej ramki (Internal Frame Listener)
Zdarzenia typu “internal frame events” pełni
ą
podobn
ą
rol
ę
dla klasy
JInternalFrame
co zdarzenia typu “window events” dla klasy
JFrame
.
Umo
ż
liwiaj
ą
one powiadomienie obiektów obsługi o tym,
ż
e "okno"
zostało
pokazane po raz pierwszy, ma by
ć
usuni
ę
te, zminimalizowane,
przywrócone, uczynione aktywnym
lub
nieaktywnym
.
Przykład 13.9.
Aplikacja
InternalFrameEventDemo
po
przyci
ś
ni
ę
ciu
jej
górnego
przycisku wy
ś
wietla wewn
ę
trzn
ą
ramk
ę
i
nasłuchuje
zdarze
ń
generowanych przez t
ę
ramk
ę
.
Obsługa
zdarze
ń
polega
na
wy
ś
wietleniu informacji o typie
wygenerowanego zdarzenia.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 41
public class InternalFrameEventDemo ...
implements InternalFrameListener ... {
...
// Metoda tworząca wewnętrzną ramkę, której zdarzeń nasłuchujemy
protected void createListenedToWindow() {
listenedToWindow = new JInternalFrame("Event Generator",
true,
// zmienność rozmiaru
true,
// zamykalne
true,
// maksymalizowalne
true);
// ikonifikowalne
listenedToWindow.setDefaultCloseOperation( /
/ Domyślne zamykanie
WindowConstants.DISPOSE_ON_CLOSE);
...
}
public void internalFrameClosing(InternalFrameEvent e) {
displayMessage("Internal frame closing", e);
}
public void internalFrameClosed(InternalFrameEvent e) {
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 42
displayMessage("Internal frame closed", e);
listenedToWindow = null;
}
public void internalFrameOpened(InternalFrameEvent e) {
displayMessage("Internal frame opened", e);
}
public void internalFrameIconified(InternalFrameEvent e) {
displayMessage("Internal frame iconified", e);
}
public void internalFrameDeiconified(InternalFrameEvent e) {
displayMessage("Internal frame deiconified", e);
}
public void internalFrameActivated(InternalFrameEvent e) {
displayMessage("Internal frame activated", e);
}
public void internalFrameDeactivated(InternalFrameEvent e) {
displayMessage("Internal frame deactivated", e);
}
void displayMessage(String prefix, InternalFrameEvent e) {
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 43
// Nasza metoda wyświetlania informacji o zdarzeniach
String s = prefix + ": " + e.getSource();
// Pobierz obiekt-źródło zdarzenia
display.append(s + newline);
}
...
// W klasie jest też obsługa akcji dla przycisku „Show Internal Frame”
public void actionPerformed(ActionEvent e) {
if (e.getActionCommand().equals(SHOW)) {
...
if (listenedToWindow == null) {
createListenedToWindow();
// Utwórz nową wewętrzną ramkę
listenedToWindow.addInternalFrameListener(this);
//Rejestruj w celu
// obsługi jej zdarzeń
...
}
}
...
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 44
}
W
interfejsie
InternalFrameListener
i
klasie
adaptera
InternalFrameAdapter
zadeklarowano metody:
void internalFrameOpened(InternalFrameEvent)
- wołana po pierwszym
narysowaniu nadzorowanej wewn
ę
trznej ramki.
void internalFrameClosing(InternalFrameEvent)
– metoda wołana po
żą
daniu u
ż
ytkownika zamkni
ę
cia wewn
ę
trznej ramki. Domy
ś
lna obsługa
w klasie
JInternalFrame
jedynie ukrywa okno dla zdarzenia zamykania
ramki. Metod
ą
klasy
JInternalFrame
o nazwie
setDefaultCloseOperation
mo
ż
na zmieni
ć
zachowanie tej obsługi na:
DISPOSE_ON_CLOSE
lub
DO_NOTHING_ON_CLOSE
(stałe w interfejsie
WindowConstants
,
implementowanym przez
JInternalFrame
).
void internalFrameClosed(InternalFrameEvent)
- wołana zaraz po
usuni
ę
ciu obiektu i zasobów wewn
ę
trznej ramki metod
ą
dispose
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 45
void internalFrameIconified(InternalFrameEvent)
void internalFrameDeiconified(InternalFrameEvent)
– metody wołane s
ą
po minimalizacji wzgl. przwróceniu wewn
ę
trznej ramki.
void internalFrameActivated(InternalFrameEvent)
void internalFrameDeactivated(InternalFrameEvent)
– metody wołane s
ą
po uczynieniu ramki aktywnej wzgl. nieaktywnej.
Ka
ż
da metoda posiada jeden parametr typu
InternalFrameEvent
- ta
klasa nie definuje u
ż
ytecznych metod. Dziedziczy ona metod
ę
getSource
po klasie
EventObject
co pozwala na pobranie obiektu ramki, który
wygenerował obsługiwane zdarzenie.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 46
7) Zdarzenia wyboru opcji (Item Listener)
Zdarzenia typu “Item events” generowane s
ą
przez komponenty
implementuj
ą
ce interfejs
ItemSelectable
. Takie komponenty zapewniaj
ą
dwustanow
ą
reprezentacj
ę
opcji (wł
ą
cz/wył
ą
cz).
Np. w
Swingu
takie zdarzenia generuj
ą
obiekty typu “
check box”, “check
box menu item”, “combo box”
.
Interfejs
ItemListener
deklaruje jedn
ą
metod
ę
:
void itemStateChanged(ItemEvent)
Metoda jest wołana zaraz po zmianie stanu nadzorowanego
komponentu. Parametrem metody jest obiekt klasy
ItemEvent
. W tej
klasie zdefiniowano metody:
Object getItem()
-
zwraca obiekt zwi
ą
zany z opcj
ą
o zmienionym stanie
– cz
ę
sto jest to napis klasy
String
b
ę
d
ą
cy tytułem wybranej opcji.
ItemSelectable
getItemSelectable()
–
zwraca
komponent,
który
wygenerował zdarzenie.
int getStateChange()
– zwraca nowy stan opcji – w klasie
ItemEvent
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 47
zdefiniowano dwa stany:
SELECTED , DESELECTED
.
Przykład 13.10
. W programie
ComponentEventDemo
(przykład 13.6)
wyst
ę
puje te
ż
kod obsługi zdarze
ń
wyboru opcji (“item events”):
...
// W kodzie inicjalizacji
checkbox.addItemListener(this);
// Rejestracja dla zdarzeń wyboru opcji
...
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
label.setVisible(true);
label.revalidate();
label.repaint();
} else {
label.setVisible(false);
}
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 48
8) Zdarzenia dla klawiatury (Key Listener)
Zdarzenia typu “key events” pojawiaj
ą
si
ę
, gdy u
ż
ytkownik
przyciska
lub
zwalnia klawisze klawiatury
. S
ą
one generowane przez
komponent
posiadaj
ą
cy w danej chwili
kontekst klawiatury
.
Zdarzenia klawiatury (“key events”):
-
“
key typed
” – wprowadzono znak w Unikodzie;
-
„
key pressed
” - przyci
ś
ni
ę
cie klawisza;
-
“
key released
” – zwolnienie klawisza.
Najcz
ęś
ciej program obsługuje tylko zdarzenia typu “wprowadzono
znak”. Obsługa dwóch pozostałych zdarze
ń
potrzebna jest jedynie
wtedy, gdy chcemy reagowa
ć
na klawisze nie reprezentuj
ą
ce znaków
widocznych lecz tzw. znaki specjalne, np.
F1
.
Uwaga:
innym mechanizmem reakcji programu na klawisze specjalne
jest stosowanie skrótów do klawiszy („key bindings”) w obiektach opcji.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 49
Proces uzyskiwania przez komponent kontekstu klawiatury:
•
metoda komponentu
isFocusTraversable
musi zwraca
ć
true
;
•
komponent wywołuje metod
ę
requestFocus
wtedy, gdy zostanie on
wybrany, np. klikni
ę
ciem myszy – w obsłudze zdarzenia myszy.
Przykłady generacji zdarze
ń
klawiaury:
•
Wprowadzenie znaku 'a' do pola tekstowego wygeneruje 3 zdarzenia:
“key pressed”, “key typed”, “key released”. Zdarzenie “key typed” nie
uzyskuje kodu klawisza ani kodu modyfikatora.
•
Wprowadzenie klawisza ‘Shift’ - pole tekstowe generuje 2 zdarzenia:
“key pressed” i “key released”.
•
Wprowadzenie znaku 'A' jednoczesnym (‘Shift’+A) – generuje
zdarzenia: “key pressed” (Shift), “key pressed” (A), “key typed” (A),
“key released” (A), “key released” (Shift).
•
Wrowadzenie znaku 'A' sekwencj
ą
(‘Caps Lock’, A) – generuje
zdarzenia: “key pressed” (Caps Lock), “key pressed” (A), “key typed”
('A'), key released (A).
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 50
Uwaga
: dla klawisza “Caps Lock” i innych klawiszy “stanu” (Scroll
Lock, Num Lock) zdarzenie „key released” generowane jest dla
nast
ę
pnej pary akcji – wcisni
ę
cia i zwolnienia tego klawisza.
Przykład 13.11.
GUI apletu składa si
ę
z edytowalnego pola tekstowego
w którym u
ż
ytkownik wprowadza znaki z klawiatury i z obszaru
tekstowego wy
ś
wietlaj
ą
cego komunikaty o zdarzeniach typu “key event”.
Przycisk na dole umo
ż
liwia wyzerowanie pola i obszaru tekstowego.
Fragment kodu obejmuj
ą
cy obsług
ę
zdarze
ń
klawiatury:
public class KeyEventDemo ... implements KeyListener ... {
...// W kodzie inicjalizacji:
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 51
typingArea = new JTextField(20);
typingArea.addKeyListener(this);
...
/** Obsługa zdarzenia “key typed” dla pola tekstowego. */
public void keyTyped(KeyEvent e) {
displayInfo(e, "KEY TYPED: ");
}
/** Obsługa zdarzenia “key pressed” dla pola tekstowego. */
public void keyPressed(KeyEvent e) {
displayInfo(e, "KEY PRESSED: ");
}
/** Obsługa zdarzenia “key released” dla pola tekstowego. */
public void keyReleased(KeyEvent e) {
displayInfo(e, "KEY RELEASED: ");
}
...
// Nasza metoda analizy wprowadzonych danych i wy
ś
wietlania
protected void displayInfo(KeyEvent e, String s){
// komunikatu
...
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 52
char c = e.getKeyChar();
// Pobierz wprowadzony znak
int keyCode = e.getKeyCode();
// Pobierz kod klawisza
int modifiers = e.getModifiers();
// Pobierz kod klawisza specjalnego
...
tmpString = KeyEvent.getKeyModifiersText(modifiers);
...// Tu wyświetlenie informacji o zdarzeniach typu KeyEvent...
}
}
W interfejsie
KeyListener
i klasie adaptera
KeyAdapter
zadeklarowano
wzgl. zdefiniowano trzy metody:
void keyTyped(KeyEvent)
– wołana po wprowadzeniu znaku Unikodu do
nadzorowanego komponentu;
void keyPressed(KeyEvent)
– wołana po naci
ś
ni
ę
ciu klawisza, gdy
nadzorowany komponent posiada kontekst klawiatury;
void keyReleased(KeyEvent)
– wołana po zwolnieniu klawisza, gdy
nadzorowany komponent posiada kontekst klawiatury;
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 53
Ka
ż
da z metod posiada jeden parametr klasy
KeyEvent
. W tej klasie
zdefiniowano po
ż
yteczne metody dla ustalenia podczas obsługi
szczegółów zdarzenia:
int getKeyChar()
void setKeyChar(char)
- pobierz lub ustaw znak Unikodu zwi
ą
zany z tym
zdarzeniem;
int getKeyCode()
void setKeyCode(int)
-
pobierz lub ustaw kod klawisza zwi
ą
zany z tym
zdarzeniem - w klasie
KeyEvent
zdefiniowano stałe reprezentuj
ą
ce kody
klawiszy – np.
VK_A
dla klawisza A,
VK_ESCAPE
dla klawisza
ESCAPE
.
void setModifiers(int)
– ustawia stan klawisza modyfikuj
ą
cego dla tego
zdarzenia – stan mo
ż
e by
ż
pobrany metod
ą
getModifiers
klasy
InputEvent
;
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 54
String getKeyText()
String getKeyModifiersText()
- zwraca opisy tekstowe klawisza wzgl.
klawisza modyfikuj
ą
cego dla zdarzenia.
Klasa
KeyEvent
dziedziczy metody z klas
InputEvent
i
ComponentEvent
.
Metody te opisane b
ę
d
ą
dla klasy
MouseEvent
:
Component getComponent()
void consume()
int getWhen()
boolean isAltDown()
boolean isControlDown()
boolean isMetaDown()
boolean isShiftDown()
int getModifiers()
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 55
9) Zdarzenia dla myszy (Mouse Listener)
Zdarzenia pochodz
ą
ce od “myszy” s
ą
generowane w wyniku interakcji
u
ż
ytkownika z komponentem za pomoc
ą
myszy (lub podobnego
urz
ą
dzenia wej
ś
ciowego).
Zdarzenia zwi
ą
zane ze zmian
ą
stanu myszy:
kursor
wchodzi
do obszaru ekranu dla komponentu,
kursor
wychodzi
z obszaru ekranu dla komponentu,
u
ż
ytkownik
wciska
przycisk myszy,
u
ż
ytkownik
zwalnia
przycisk myszy,
klikni
ę
cie
„lewym” przyciskiem myszy.
Zdarzenia zwi
ą
zane z ruchem myszy zebrane s
ą
w odr
ę
bny typ
zdarze
ń
MouseMotionListener
.
Klasa adaptera
MouseInputAdapter
implementuje oba interfejsy:
MouseListener
i
MouseMotionListener
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 56
Przykład 13.12
. Aplet
MouseEventDemo
zawiera obsług
ę
zdarze
ń
myszy
dla górnego obszaru (pustego) (BlankArea) i dla kontenera
zawieraj
ą
cego ten obszar (klasa MouseEventDemo). O wygenerowanym
zdarzeniu informuje tekst pojawiaj
ą
cy si
ą
w dolnym obszarze tekstowym.
Kod obsługi zdarze
ń
myszy:
public class MouseEventDemo ... implements MouseListener {
...// W kodzie inicjalizacji:
// Rejestracja obsługi zdarze
ń
myszy dla “blankArea” i panelu.
blankArea.addMouseListener(this);
addMouseListener(this);
...
public void mousePressed(MouseEvent e) {
// Obsługa przyciśnięcia
saySomething("Mouse pressed; # of clicks: "
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 57
+ e.getClickCount(), e);
}
public void mouseReleased(MouseEvent e) { /
/ Obsługa zwolnienia
saySomething("Mouse released; # of clicks: "
+ e.getClickCount(), e);
}
public void mouseEntered(MouseEvent e) {
// Obsługa wejścia
saySomething("Mouse entered", e);
}
public void mouseExited(MouseEvent e) {
// Obsługa wyjścia
saySomething("Mouse exited", e);
}
public void mouseClicked(MouseEvent e) {
// Obsługa kliknięcia
saySomething("Mouse clicked (# of clicks: "
+ e.getClickCount() + ")", e);
}
void saySomething(String opis, MouseEvent e) {
textArea.append(opis + " detected on "
+ e.getComponent().getClass().getName()
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 58
+ "." + newline);
}
}
Interfejs
MouseListener
i jego adapter
MouseAdapter
deklaruj
ą
metody:
void mouseClicked(MouseEvent)
– wołana zaraz po klikni
ę
ciu przez
u
ż
ytkownika nadzorowanego komponentu;
void mouseEntered(MouseEvent)
– wołana zaraz po wprowadzeniu
kursora w obszar ekranu dla nadzorowanego komponentu;
void mouseExited(MouseEvent)
– wołana zaraz po wyprowadzeniu
kursora z obszaru ekranu dla nadzorowanego komponentu;
void mousePressed(MouseEvent)
– wołana zaraz po przyci
ś
ni
ę
ciu
przycisku myszy podczas, gdy kursor znajduje si
ę
w obszaru ekranu dla
nadzorowanego komponentu;
void mouseReleased(MouseEvent)
– wołana zaraz po zwolnieniu
przycisku myszy podczas, gdy kursor znajduje si
ę
w obszaru ekranu dla
nadzorowanego komponentu;
Uwaga.
Gdy u
ż
ytkownik “przeci
ą
ga” komponent – przyciska i trzyma
przyci
ś
ni
ę
ty przycisk a w tym czasie przesuwa kursor myszy – zdarzenia
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 59
„
mouse
entered
”,
„
mouse
exited
”,
„
mouse
released
”
dotycz
ą
przeci
ą
ganego komponentu wł
ą
cznie z ko
ń
cowym „
mouse released
”.
Ka
ż
da z powy
ż
szych metod posiada parametr klasy
MouseEvent
.
W tej klasie zdefiniowano kilka po
ż
ytecznych metod:
int getClickCount()
– zwraca liczb
ę
szybko po sobie nast
ę
puj
ą
cych
klikni
ęć
, np. 2 dla „double click”;
int getX()
int getY()
Point getPoint()
-
zwracaj
ą
współrz
ę
dne kursora, gdy zdarzenie zaszło,
wzgl
ę
dem punktu odniesienia komponentu;
boolean isPopupTrigger()
-
zwraca warto
ść
„true”, gdy zdarzenie myszy
powinno wy
ś
wietli
ć
„pop-up” menu; powinno by
ć
wołane podczas
obsługi zdarze
ń
typu „mouse pressed” i „mouse released” dla wszystkich
komponentów, które mog
ą
zawiera
ć
„pop-up” menu.
Klasa
MouseEvent
dziedziczy te
ż
po
ż
yteczn
ą
metod
ę
z klasy
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 60
ComponentEvent
:
Component getComponent
– zwraca komponent, który wygenerował
zdarzenie; mo
ż
e by
ż
wykorzystana zamiast bardziej ogólnej metody
getSource
.
Klasa
MouseEvent
dziedziczy te
ż
kilka po
ż
ytecznych metod z klasy
InputEvent
:
int getWhen()
– zwraca indeks chwili czasowej, gdy zdarzenie to
wyst
ą
piło – im wy
ż
sza warto
ść
indeksu tym bli
ż
sza jest ta chwila
aktualnej chwili.
boolean isAltDown()
boolean isControlDown()
boolean isMetaDown()
boolean isShiftDown()
– zwraca stan indywidualnych klawiszy
modyfikujacych w chwili zaj
ś
cia zdarzenia;
int getModifiers()
– zwraca stan wszystkich klawiszy modyfikuj
ą
cych i
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 61
przycisków myszy w chwili, gdy wyst
ą
piło to zdarzenie; w klasie
InputEvent zdefiniowano stałe dla rozpatrywanych przycisków i klawiszy:
ALT_MASK, BUTTON1_MASK, BUTTON2__MASK,
BUTTON3_MASK, CTRL_MASK, META_MASK, SHIFT_MASK.
Np. poni
ż
sze wyra
ż
enie jest prawdziwe gdy wci
ś
ni
ę
to prawy przycisk
myszy:
(mouseEvent.getModifiers() & InputEvent.BUTTON3_MASK)
== InputEvent.BUTTON3_MASK
W klasie
SwingUtilities
istniej
ą
metody sprawdzaj
ą
ce, czy wci
ś
ni
ę
to
przycisk myszy:
static boolean isLeftMouseButton(MouseEvent)
static boolean isMiddleMouseButton(MouseEvent)
static boolean isRightMouseButton(MouseEvent)
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 62
10) Zdarzenia ruchu myszy (Mouse Motion Listener)
Zdarzenia typu “mouse-motion events” s
ą
reakcj
ą
na ruch kursora na
ekranie sterowany mysz
ą
(lub podobnym urz
ą
dzeniem wej
ś
ciowym).
Interfejs
MouseMotionListener
i klasa adaptera
MouseMotionAdapter
deklaruj
ą
dwie metody:
•
void mouseDragged(MouseEvent)
– wołana dla ruchu myszy w
sytuacji, gdy przycisk myszy jest wci
ś
ni
ę
ty – zdarzenie generowane
jest przez komponent, który uprzednio wygenerował te
ż
zdarzenie
„mouse pressed”, nawet je
ś
li kursor nie znajduje si
ę
ju
ż
nad tym
komponentem.
•
void mouseMoved(MouseEvent)
- wołana dla ruchu myszy, gdy
przyciski myszy nie s
ą
wci
ś
ni
ę
te – zdarzenie generowane jest przez
komponent znajduj
ą
cy sie aktualnie pod kursorem.
Uwaga: parametr obu metod jest klasy
MouseEvent
.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 63
Przykład 13.13.
Aplet
MouseMotionEventDemo
ilustruje obsług
ę
ruchu
kursora
w
górnym
obszarze
pustym.
Implementuje
metody
mouseDragged
i
mouseMoved
podaj
ą
c w dolnym obszarze tekstowym
informacj
ę
o współrz
ę
dnych kursora.
Kod implementuj
ą
cy obsług
ę
zdarze
ń
ruchu myszy:
public class MouseMotionEventDemo extends JApplet
implements MouseMotionListener {
//...W kodzie inicjalizacji:
// Rejestracja dla zdarze
ń
ruchu myszy w obszarze blankArea i
// całego apletu (panelu).
blankArea.addMouseMotionListener(this);
addMouseMotionListener(this);
...
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 64
}
public void mouseMoved(MouseEvent e) {
// Ruch myszy
saySomething("Mouse moved", e);
}
public void mouseDragged(MouseEvent e) {
// Pochwycenie myszą
saySomething("Mouse dragged", e);
}
void saySomething(String opis, MouseEvent e) {
textArea.append(opis
+ " (" + e.getX() + "," + e.getY() + ")"
+ " detected on "
+ e.getComponent().getClass().getName()
+ newline);
}
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 65
Przykład 13.14.
Program
SelectionDemo
wyrysowuje prostok
ą
t jako
reakcj
ę
na zdarzenie przeci
ą
gania mysz
ą
. Zawiera obsług
ą
trzech
zdarze
ń
myszy: “
mouse press”, “mouse drag”, “mouse release
”.
Wymaga
to
implementacji
obu
interfejsów:
MouseListener
i
MouseMotionListener.
W tym celu dziedziczymy z klasy adaptera
MouseInputAdapter
.
...// W kodzie inicjalizacji w klasie głównej :
MyListener myListener = new MyListener();
addMouseListener(myListener);
addMouseMotionListener(myListener);
...
// Klasa dla obsługi zdarze
ń
myszy
class MyListener extends MouseInputAdapter {
public void mousePressed(MouseEvent e) {
int x = e.getX();
int y = e.getY();
currentRect = new Rectangle(x, y, 0, 0);
updateDrawableRect(getWidth(), getHeight());
repaint();
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 66
}
public void mouseDragged(MouseEvent e) {
updateSize(e);
}
public void mouseReleased(MouseEvent e) {
updateSize(e);
}
void updateSize(MouseEvent e) {
int x = e.getX();
int y = e.getY();
...
repaint(...);
}
}
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 67
13.5 Klasy
AbstractAction, Action
1) Klasa
Action
Je
ś
li zdarzenia dla dwóch lub wi
ę
cej komponentów prowadz
ą
do
wykonania tej samej funkcji programu to sensowne staje si
ę
:
•
wprowadzenie wspólnego typu zdarzenia, np.
ActionListener
,
•
utworzenie jednego obiektu klasy
Action
implementuj
ą
cego t
ę
funkcj
ę
.
Zdarzenia „akcji”
generuje szereg komponentów: przyciski, opcje menu,
pola tekstowe, pola wyboru, itd.
Klasy posiadaj
ą
ce metody
setAction
i
getAction
:
AbstractButton , JComboBox , JTextField
Przykład 13.15.
Obsługa zdarzenia akcji dla przycisku i opcji menu
b
ę
dzie wykonywa
ć
t
ę
sam
ą
funkcj
ę
:
Action leftAction = new LeftAction();
...
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 68
button = new JButton(leftAction)
...
menuItem = new JMenuItem(leftAction);
Pó
ź
niejsze
ni
ż
w trakcie inicjalizacji
doł
ą
czenie obiektu „akcji” do
komponentu
nast
ę
puje zwykle metod
ą
setAction
.
Obiekt typu
Action
doł
ą
czony do komponentu
jest domy
ś
lnie
zarejestrowany
dla obsługi zdarze
ń
akcji (“action events”) komponentu.
Obiekt typu
Action
zapewnia obsług
ę
zdarze
ń
akcji i mo
ż
e te
ż
zapewni
ć
centralne zarz
ą
dzanie stanem
komponentu generuj
ą
cego takie
zdarzenia:
-
stan komponentu
odpowiada stanowi obiektu akcji; np. obiekt akcji
przekazuje komponentowi tekst i ikonk
ę
;
-
zmiana stanu obiektu akcji
powoduje odpowiedni
ą
zmian
ę
stanu
wszystkich komponentów, do których jest doł
ą
czony.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 69
Utworzenie przez programist
ę
własnej obsługi poprzez obiekt typu
Action
polega na:
•
zdefiniowaniu klasy pochodnej od klasy
AbstractAction
i
•
utworzeniu jej obiektu, pod warunkiem,
ż
e
•
ta klasa pochodna implementuje metod
ę
actionPerformed
.
Przykład 13.15 (c.d.)
Definicja własnej klasy
LeftAction
pochodnej po
AbstractAction
i utworzenie jej obiektu
leftAction
.
// W klasie głównej ActionDemo
leftAction = new LeftAction("W lewo", anIcon,
"To jest lewy przycisk.",
new Integer(KeyEvent.VK_L));
// ALT + L
- klawisz skrótu
...
// Klasa LeftAction
class LeftAction extends AbstractAction {
public LeftAction(String text, ImageIcon icon,
String desc, Integer mnemonic) {
super(text, icon);
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 70
// Ustaw własno
ść
obiektu akcji
putValue(SHORT_DESCRIPTION, desc);
// Tekst wskazówki oraz
putValue(MNEMONIC_KEY, mnemonic);
// ... klawisz skrótu
}
// Obsługa zdarzenia akcji
public void actionPerformed(ActionEvent e) {
displayResult("Akcja dla przycisku 1 / opcji menu", e);
}
}
Program
ActionDemo
zawiera definicje
trzech akcji
– ka
ż
da z nich
dołaczona jest do
przycisku
i
opcji menu.
Skróty klawiszy aktywuj
ą
: Alt-L
(lewy przycisk), Alt-M (
ś
rodkowy przycisk), Alt-R (prawy przycisk).
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 71
Stany 3 obiektów akcji (dozwolona/niedozwolona) mo
ż
na ustawia
ć
w
pod-menu „Action State”. Kod realizuj
ą
cy ustawienie stanu akcji:
boolean selected =
... // true jesli akcja jest dozwolona
;
//false, jesli akcja jest zabroniona
leftAction.setEnabled(selected);
Po utworzeniu komponentów wykorzystuj
ą
cych obiekty akcji mo
ż
na
zmieni
ć
indywidualne komponenty. Np. przez usuni
ę
cie ikony (w menu)
lub usuni
ę
cie tekstu (w przyciskach):
menuItem = new JMenuItem();
menuItem.setAction(leftAction);
menuItem.setIcon(null);
//
Usuwa ikon
ę
z menu.
...
button = new JButton();
button.setAction(leftAction);
button.setText("");
//
Na razie przycisk nie zawiera tekstu
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 72
2) Klasa
AbstractAction
AbstractAction()
AbstractAction(String)
AbstractAction(String, Icon)
Konstruktory. Parametry umo
ż
liwiaj
ą
ustawienie tekstu i ikonki dla
kontrolowanego przez akcj
ę
komponentu.
void setEnabled(boolean)
boolean isEnabled()
Ustaw wzgl. sprawd
ź
, czy zdarzenia komponentu kontrolowanego przez
akcj
ę
s
ą
dozwolone.
void putValue(String, Object)
Object getValue(String)
Ustaw własno
ść
lub pobierz obiekt zwi
ą
zany z własno
ś
ci
ą
obiektu akcji.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 73
3) Własno
ś
ci akcji
Obiekt klasy
AbstractAction
posiada szereg własno
ś
ci, których
ustawianie powoduje automatycznie zmian
ę
odpowiednich ustawie
ń
komponentów, do których obiekt akcji jest doł
ą
czony.
Np. ustawienie własno
ś
ci
ACCELERATOR_KEY
dla akcji po dołaczeniu
akcji do opcji menu spowoduje automatyczne wywołanie metody
JMenuItem.setAccelerator(KeyStroke)
, gdzie
KeyStroke
identfikuje typ dla
zestawu klawiszy – akceleratorów.
Własno
ść
Automatycznie wpływa na
obiekt klasy
(wywoływana metoda)
Cel
ACCELERATOR_KEY
JMenuItem
(setAccelerator)
Akcelerator umo
ż
liwia
wybranie opcji niezale
ż
nie
od jej widoczno
ś
ci.
ACTION_COMMAND_KEY
AbstractButton, JCheckBox,
JRadioButton
(setActionCommand)
Napis rozkazu zwi
ą
zany
ze zdarzeniem akcji.
13. Swing - obsługa zdarze
ń
W. Kasprzak: Programowanie zdarzeniowe
13 - 74
LONG_DESCRIPTION
brak
Dłu
ż
szy opis akcji.
MNEMONIC_KEY
AbstractButton,
JMenuItem, JCheckBox,
JRadioButton
(setMnemonic)
Skrót dla akcji
NAME
AbstractButton,
JMenuItem, JCheckBox,
JRadioButton
(setText)
Nazwa akcji.
SHORT_DESCRIPTION
AbstractButton, JCheckBox,
JRadioButton
(setToolTipText)
Wskazówka o akcji
SMALL_ICON
AbstractButton, JMenuItem
(setIcon)
Ikona akcji.