background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 1 

 

10. Swing – układanie i malowanie 

 

10.1 Zarz

ą

dzenie układem i malowanie kontenera 

10.2 Klasa 

JComponent 

i malowanie komponentu  

10.3 Wzorce projektowe 

Composite

 i 

Decorator

 

10.4 W

ą

tek rozdziału zdarze

ń

 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 2 

10.1 Zarz

ą

dzanie układem i malowanie kontenera 

1) Zarz

ą

dzanie układem komponentów w kontenerze 

Poni

Ŝ

ej  podano  5  ró

Ŝ

nych  układów  komponentów.  W  czasie  realizacji 

kontenera  okre

ś

lane  s

ą

  rozmiary  i  poło

Ŝ

enia  komponentów.  6-ty 

menad

Ŝ

er układu to 

CardLayout 

 układ o charakterze zakładek.

 

 

 

Menad

Ŝ

erowie 

(zarz

ą

dcy) układu: 

BorderLayout, 

GridLayout, 

FlowLayout, 

BoxLayout, 

GridBagLayout, 

CardLayout

 

 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 3 

Ka

Ŝ

dy kontener posiada 

domy

ś

lnego

 menad

Ŝ

era układu : 



 dla obiektów klasy 

JPanel

 jest nim 

FlowLayout

 



 dla  paneli  zawarto

ś

ci  (głównych  kontenerów  w  obiektach 

JApplet

JDialog

 i 

JFrame

) jest nim 

BorderLayout

 
O  zastosowanym  menad

Ŝ

erze  układu  powinni

ś

my  decydowa

ć

  w  chwili 

tworzenia obiektu klasy 

JPanel

 lub podczas dodawania komponentów do 

panelu zawarto

ś

ci.  

Zmian

ę

  menad

Ŝ

era  umo

Ŝ

liwia  metoda  kontenera 

setLayout

.  Np. 

fragment kodu ustawiaj

ą

cy menad

Ŝ

era 

BorderLayout

:  

JPanel pane = new JPanel(); 
pane.setLayout(new BorderLayout()); 

 



 

BorderLayout  

Posiada 

obszarów 

przeznaczonych 

dla  

komponentów:  

North, South, East, West, Center

.  

 

 

 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 4 

BoxLayout  

Komponenty  rozmieszczane  s

ą

  w  kolumnie  lub 

wierszu. 

Zachowane 

s

ą

 

maksymalne 

rozmiary 

komponentu i mo

Ŝ

liwe jest przyleganie komponentów.

 

 

FlowLayout  

Wypełnia komponentami wiersze od lewej do prawej i kontynuje w razie 
potrzeby w dalszym wierszu. 

 

GridLayout  

Normalizuje rozmiary komponetów i wy

ś

wietla 

je w zadanej liczbie wierszy i kolumn. 

 

 

 

GridBagLayout  

Umo

Ŝ

liwia 

elastyczny 

dobór 

rozmiarów 

wierszy i kolumn.

 

 

 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 5 

Preferowany rozmiar komponentu  

Na rzecz komponentu mo

Ŝ

liwe s

ą

 wywołania metod: 

setMinimumSize, setPreferredSize, setMaximumSize  

lub nadpisanie metod 

getMinimumSize, getPreferredSize, getMaximumSize.  

Jedynie  menad

Ŝ

er 

BoxLayout

  zwraca  uwag

ę

  na  wymagany  przez 

komponent maksymalny rozmiar. 
 

Preferowane poło

Ŝ

enie komponentu  

Wywołania metod komponentu: 

setAlignmentX , setAlignmentY  

lub nadpisanie metod  

getAlignmentX , getAlignmentY . 

Jedynie  menad

Ŝ

er 

BoxLayout

 

zwraca  uwag

ę

  na  wymagane  przez 

komponent poło

Ŝ

enie. 

 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 6 

Przebieg ustalania rozmiaru i poło

Ŝ

enia ramki 

JFrame

 

Metoda 

pack()

  sprawia, 

Ŝ

e  komponent  klasy 

JFrame

  posiada 

preferowany 

rozmiar.  

1.  Preferowany  rozmiar  ramki  wynika  z  dodania  rozmiarów 

brzegu 

ramki

  do 

preferowanego  rozmiaru  komponentów

  bezpo

ś

rednio 

zawartych  w  ramce,  czyli  równa  si

ę

  sumie  preferowanych  rozmiarów 

panelu zawarto

ś

ci ramki

 ("content pane") i 

paska menu

2.  Zarz

ą

dca  układu  dla  "content  pane"  (zwykle  jest  nim 

BorderLayout

okre

ś

la 

preferowany rozmiar

 tego "ukrytego" kontenera. Zale

Ŝ

y on od: 

 

rozmiarów brzegu 

panelu zawarto

ś

ci i od 

 

preferowanych rozmiarów komponentów

, zawartych w tym panelu. 

Np.  zarz

ą

dca 

GridLayout

  stara  si

ę

  dopasowa

ć

  szeroko

ść

  i  wysoko

ść

 

ka

Ŝ

dego  zarz

ą

dzanego  komponentu  do  najszerszego  i  najwy

Ŝ

szego  z 

nich.  

3.  Ka

Ŝ

dy 

komponent

  podaje  zarz

ą

dcy  układu  swoje 

preferowane

 

rozmiary

 lub zwraca rozmiar wynikaj

ą

cy ze 

ś

rodowiska "

look and feel

". 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 7 

4.  Po  wyznaczeniu  rozmiarów  komponentów,  ustalany  jest  rozmiar  ich 
kontenera i ten wynik 

propagowany jest w gór

ę

 hierarchii

 komponentów. 

 

2) Malowanie komponentów kontenera 

Zasady malowania komponentu  

1.  Proces  wykre

ś

lania  rozpoczyna  si

ę

  od 

najwy

Ŝ

szego  komponentu

  w 

hierarchii, który ma by

ć

 malowany (po raz pierwszy lub od

ś

wie

Ŝ

ony). 

2.  Komponenty  Swing-a 

domy

ś

lnie  od

ś

wie

Ŝ

aj

ą

  swój  wygl

ą

d  po 

modyfikacji.  Np.  w  wyniku  wywołania  metody 

setText

()

  komponent 

zostanie zmodyfikowany i ewentualnie zmieni

ą

 si

ę

 jego rozmiary.  

3.  Je

ś

li  zmiana  poło

Ŝ

enia  lub  rozmiaru  komponentu  nie  nast

ę

puje 

automatycznie to mo

Ŝ

na j

ą

 wymusi

ć

 metod

ą

 

revalidate()

 a potem nale

Ŝ

wywoła

ć

 

repaint()

.

 

4. Kod malowania wykonuje si

ę

 w 

w

ą

tku rozdziału zdarze

ń

5.  Malowanie  jest 

podwójnie  buforowane

  -  najpierw  wypełniany  jest 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 8 

"wirtualny bufor ekranu" i dopiero po zako

ń

czeniu malowania odbywa si

ę

 

opró

Ŝ

nienie tego bufora i przesłanie jego zawarto

ś

ci do bufora ekranu.  

 

Metoda 

setOpaque

 

Mo

Ŝ

na  przekaza

ć

  do  zarz

ą

dcy  malowania  informacj

ę

  o  tym, 

Ŝ

komponent 

jest nieprzezroczysty

 - metod

ą

 

setOpaque(true)

 

- co zwi

ę

kszy 

efektywno

ść

 procesu rysowania.  

Wprawdzie  komponentom  odpowiadaj

ą

  zawsze 

prostok

ą

tne  obszary

  to 

jednak  przezroczyste  komponenty  mog

ą

  mie

ć

  dowolny  kształt, 

odsłaniaj

ą

c fragmenty przykrywanego komponentu. 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 9 

Przykład.

  Dany  jest  interfejs  u

Ŝ

ytkownika  i  tworz

ą

ca  go  hierarchia 

kontenerów. 

 

 

 

Proces malowania powy

Ŝ

szego graficznego interfejsu:   

1. 

Kontener główny

 typu 

JFrame

 maluje si

ę

 samodzielnie jako pierwszy.  

2. 

Kontener  "content  pane

"  najpierw  maluje  tło  -  szary,  jednorodny 

czworok

ą

t.  Nast

ę

pnie  wzywa  on  zawarty  w  nim  obiekt  typu 

JPanel

  do 

malowania si

ę

.  

Zwró

ć

my  uwag

ę

  na  fakt, 

Ŝ

e  panel  zawarto

ś

ci  powinien  by

ć

 

nieprzezroczysty

.  Poniewa

Ŝ

 

JPanel

  jest  nieprzezroczysty  mo

Ŝ

na  by  go 

wykorzysta

ć

 w roli "content pane", tzn. zamiast 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 10 

 

content=frame

.

getContentPanel()

 i  

 

content.add(panel)

  // dodania naszego panelu do „content pane” 

mogliby

ś

my ustawi

ć

 „content pane” na nasz panel dzi

ę

ki:  

setContentPane(panel)

.

 

3. 

Kontener  typu

  JPanel

  zawarty  w  „content  pane”  maluje  najpierw 

swoje  tło  -  szary,  jednorodny  prostok

ą

t.  Nast

ę

pnie  maluje  swój  brzeg  - 

jest  on  w  tym  przypadku  typu 

EmptyBorder 

–  brzeg  zwi

ę

ksza 

preferowany  rozmiar  panelu.  Na  koniec  panel  wzywa  "swoje" 
komponenty aby po kolei same "malowały si

ę

".  

4. 

Komponent 

JButton

  maluje  prostok

ą

tne  tło  (je

ś

li  wyst

ę

puje)  i 

nast

ę

pnie  maluje  swój  tekst.  Je

ś

li  przycisk  posiada  aktualnie  kontekst 

klawiatury  to  jego  wygl

ą

d  jest  zmieniany  zgodnie  z  przyj

ę

tym 

ś

rodowiskiem "look-and-feel".  

5. 

Komponent

 JLabel

 maluje swoje tło i swój tekst.  

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 11 

10.2 Klasa 

JComponent

 i malowanie komponentu 

Bazowa  klasa  komponentów  Swing-a  to  klasa 

JComponent

,  która 

dziedziczy z klasy 

Container,

 a ta z kolei dziedziczy z klasy 

Component

Klasa 

Component

  –  zapewnia  wszystkie  podstawowe  funkcje 

komponentu od ustawiania ich wygl

ą

du po malowanie i zdarzenia.  

Klasa 

Container

  –  wspomaga  dodawanie  komponentów  do  kontenera  i 

zarz

ą

dzanie rozkładem komponentów. 

 

1) Cechy klasy 

JComponent  



 Ustawianie wygl

ą

du komponentu  

Metoda 

setBorder

 umo

Ŝ

liwia okre

ś

lenie brzegu komponentu.  

Inne  metody  pozwalaj

ą

  na  ustawianie  kolorów  (

setForeground, 

setBackground

),  czcionki  (

setFont

),  przezroczysto

ś

ci  (

setOpaque

)  i 

kursora (

setCursor

). 

 



 Malowanie komponentu 

Metoda  główna 

paint

  nie  jest  jawnie  wywoływana  i  nie  mo

Ŝ

e  by

ć

 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 12 

przesłaniana.  Wywołuje  ona  metody 

paintComponent

paintBorder

  i 

paintChildren

.  Z  nich  jedynie  metoda 

paintComponent

  mo

Ŝ

e  by

ć

 

przesłaniana  i  wtedy  wyznacza  ona  własny  kod  u

Ŝ

ytkownika  dla 

rysowania komponentu.  
Jawnie wywoływanymi metodami s

ą

 te

Ŝ

:  

 

repaint 

(wymusza,  aby  cało

ść

  lub  cz

ęść

  w  podanym  prostok

ą

cie 

obszaru komponentu została odmalowana)

,  

 

revalidate  (

wymusza  ponowne  obliczenie  rozkładu  dla  kontenera 

komponentu i prowadzi do odpowiedniego odmalowania). 

 



 “Look and feel”  

Ka

Ŝ

dy  obiekt  klasy 

JComponent

  posiada  zwi

ą

zany  z  nim  obiekt  klasy 

ComponentUI,

  który  realizuje  jego  rysowanie,  obsług

ę

  zdarze

ń

wyznacza  rozmiary,  itp.  Rodzaj  obiektu 

ComponentUI

  specyfikowany 

jest  niejawnie  ustawieniem  “look  and  feel”  wynikaj

ą

cym  z  wykonania  w 

programie metody 

UIManager.SetLookAndFeel

 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 13 



 Wspomaganie rozkładu komponentów  

Klasa 

Component

  posiadała  metody  pobierania  wymaga

ń

  komponentu, 

np. 

getMinimumSize, getMaximumSize,

 

getPreferredSize

getAlignmentY 

getAlignmentX

,  a  klasa 

JComponent 

dodaje  do  nich  metody 

umo

Ŝ

liwiaj

ą

ce ustawianie tych własno

ś

ci – 

setPreferredSize,  setMinimumSize,  setMaximumSize,  setAlignmentX 

setAlignmentY.  

Istniej

ą

  te

Ŝ

  metody  do  ustawiania  i  pobierania  menad

Ŝ

era  układu 

komponentu  (

setLayout,  getLayout

)  oraz  ustawienia  kierunku  - 

zorientowania komponentu (

applyComponentOrientation

).  

 



 Zarz

ą

dzanie hierarchi

ą

 komponentów zawartych w kontenerze  

Metody dodaj

ą

ce komponent do kontenera (

add

) i usuwaj

ą

ce komponent 

z kontenera (

remove

). Metody informuj

ą

ce o hierarchii w kontenerze: 

 

getRootPane

 – podaje kontener pełni

ą

cy rol

ę

 “root pane” w kontenerze. 

 

getComponentCount

 - podaje liczb

ę

 komponentów tego kontenera, 

 

getComponent,  getComponents

  -  pobiera  jeden  (o  podanym  indeksie) 

lub wszystkie komponenty tego kontenera,  

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 14 

 

getParent

 - podaje bezpo

ś

redni kontener tego komponentu; 

 

getTopLevelAncestor

 - pobiera główny kontener dla tego komponentu. 

 



 Własno

ś

ci ustawiane przez u

Ŝ

ytkownika 

U

Ŝ

ytkownik  mo

Ŝ

e  okre

ś

li

ć

  własno

ś

ci  (pary  „nazwa/obiekt”)  dla  ka

Ŝ

dego 

obiektu  klasy 

JComponent.

  Za  ich  pomoc

ą

  mo

Ŝ

e  on  sterowa

ć

 

przetwarzaniem danych swoich komponentów. 
Metody 

putClientProperty

  i 

getClientProperty

  słu

Ŝą

  do  nadawania 

warto

ś

ci i pobierania warto

ś

ci własno

ś

ciom komponentu. 

 



 Wspomaganie dost

ę

pu do stanu komponentu 

Szereg  metod  klasy 

JComponent 

umo

Ŝ

liwia  pobranie  lub  ustawianie 

stanu  komponentu.  Np. 

setName,  getName,  setEnabled,  isEnabled, 

setVisible, isVisible, isShowing 

(sprawdza,

 

czy komponent i jego kontener 

s

ą

 namalowani na ekranie),

 setToolTipText

 



 Wspomaganie dost

ę

pu do rozmiaru i poło

Ŝ

enia komponentu  

Szereg metod pozwala na ustawianie i pobranie rozmiaru i poło

Ŝ

enia: 

getWidth,  getHeight,  getSize,  setSize 

(pobierz  aktualn

ą

  szeroko

ść

  wzgl. 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 15 

wysoko

ść

  komponentu  w  pikselach,  pobierz  wzgl.  ustaw  rozmiar 

komponentu),  

getX, getY, getBounds, setBounds 

(pobierz aktualn

ą

 współrz

ę

dn

ą

 x wzgl. 

y  punktu  odniesienia  komponentu  lub  pobierz  wzgl.  ustaw  poło

Ŝ

enie 

obejmuj

ą

cego  prostok

ą

ta  komponentu,  wszystko  wzgl

ę

dem  górnego 

lewego rogu przodka) 

getLocation, 

getLocationOnScreen, 

setLocation 

(pobierz 

aktualne 

poło

Ŝ

enie  komponentu  wzgl

ę

dem  górnego  lewego  rogu  przodka  wzgl. 

ekranu lub ustaw to poło

Ŝ

enie wzgl

ę

dne komponentu),  

getInsets

 (pobierz rozmiar brzegu komponentu).  

 



 Obsługa zdarze

ń

  

Metody  pozwalaj

ą

ce  zarejestrowa

ć

  lub  wyrejestrowa

ć

  obiekt  obsługi 

zdarzenia komponentu:  
dla przycisków myszy (

addMouseListener, removeMouseListener)

,  

ruchu  myszy    (

addMouseMotionListener,  removeMouseMotionListener

), 

klawiatury (

addKeyListener, removeKeyListener

) i zdarzenia zwi

ą

zane ze 

zmian

ą

  stanu  komponentu  –  ukrycia  widoczno

ś

ci,  przywrócenia 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 16 

widoczno

ś

ci, 

przesuni

ę

cia 

poło

Ŝ

enia, 

zmiany 

rozmiarów, 

itd. 

(

addComponentListener, removeComponentListener

). 

 



 Wspomaganie mechanizmu ”drag and drop  

Istniej

ą

  metody  wspomagaj

ą

ce  wymian

ę

  danych  przez  schowek 

systemowy  lub  mechanizm  przeci

ą

gania  komponentu  „drag  and  drop” 

(

setTransferHandler,  getTransferHandler

)  oraz  sprawdzaj

ą

ce  czy  dany 

punkt ekranu znajduje si

ę

 wewn

ą

trz obszaru komponentu (

contains

) albo 

jaki 

komponent 

najwy

Ŝ

szego 

poziomu 

zawiera 

ten 

punkt 

(

getComponentAt

). 

 



 Skróty klawiszy  

Akcje 

zdefiniowane 

dla 

komponentu 

mog

ą

 

by

ć

 

aktywowane  

przyci

ś

ni

ę

ciami  klawiszy,  np.  je

ś

li  przycisk  posiada  aktualny  kontekst 

klawiatury  to  naci

ś

ni

ę

cie  klawisza  „spacja”  jest  równowa

Ŝ

ne  z 

klikni

ę

ciem 

mysz

ą

Zwi

ą

zanie 

akcji 

klawiszami 

nast

ę

puje 

automatycznie dzi

ę

ki mechanizmowi „

look and feel

”.  

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 17 

2) Malowanie komponentu 

W celu wymalowania siebie samego obiekt klasy 

JComponent

 korzysta z 

trzech metod, wywoływanych w nast

ę

puj

ą

cej kolejno

ś

ci: 



 

paintComponent

 

–  główna  metoda  malowania  –  domy

ś

lnie  pierwsza 

czynno

ść

  to  odtwarzanie  tła  je

ś

li  komponent  jest  nieprzezroczysty  – 

nast

ę

pnie ewentualny kod malowania stworzony przez programist

ę

.  



 

paintBorder

  –  nakazuje  rysowanie  siebie  brzegowi  komponentu  (je

ś

li 

istnieje) – ta metoda nie powinna by

ć

 wywoływana lub przesłaniania. 



 

paintChildren

  -  nakazuje  rysowanie  siebie  komponentom-potomkom 

zawartym w danym kontenerze (je

ś

li istniej

ą

) – ta metoda nie powinna 

by

ć

 wywoływana lub przesłaniania. 

 
Powy

Ŝ

sze trzy metody s

ą

 wołane w metodzie klasy 

JComponent

 - 

paint

która nie powinna by

ć

 przesłaniana. 

 
Standardowa  realizacja  malowania  komponentu 

Swinga

  (ale  nie  dla 

samej  klasy 

JComponent

)  metod

ą

 

paintComponent 

ś

rodowisku  look-

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 18 

and-feel

 

jest  delegowana  do  pewnego  obiektu  (klasy 

ComponentUI

), 

który realizuje nast

ę

puj

ą

ce kroki: 



 sprawdza, czy komponent jest nieprzezroczysty, 



 je

ś

li tak, maluje tło całego obszaru komponentu, 



 ewentualnie maluje elementy wynikaj

ą

ce ze 

ś

rodowiska look-and-feel

 

Podwójne buforowanie

 zapewnia płynne rysowanie GUI na ekranie. 

 

Przykład.

  Ilustracja  kolejno

ś

ci  rysowania  w  ka

Ŝ

dym  komponencie 

dziedziczonym z klasy 

JComponent

 : 

1. tło (je

ś

li 

nieprzezroczyste)  

2. rysowanie według 

kodu u

Ŝ

ytkownika 

(je

ś

li wyst

ę

puje) 

3. obramowanie 
(je

ś

li wyst

ę

puje)  

4. zawarte 

komponenty 

(je

ś

li wyst

ę

puj

ą

)  

 

 

 

 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 19 

3) Metoda 

paintComponent

 

Przykład 10.1 

Wizualizacja obrazu, o normalnym rozmiarze i rozci

ą

gni

ę

tego wszerz. 

class ImagePanel extends JPanel { 
    ... 
    public void paintComponent(Graphics g) { 
        super.paintComponent(g); 

// Rysuj tło

 

        // Obraz o normalnym rozmiarze 

        g.drawImage(image, 0, 0, this); 

// Rozmiar obrazu to 85 x 62  

        // Obraz rozci

ą

gni

ę

ty wszerz  

        g.drawImage(image, 90, 0, 300, 62, this); 
    } 

 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 20 

W podanym przykładzie do 

rysowania tła

 wykorzystano 

paintComponent

 

z  nadklasy.  Mo

Ŝ

na  te

Ŝ

 

jawnie 

w  kodzie 

paintComponent

  poda

ć

  na 

pocz

ą

tku sekwencj

ę

 instrukcji: 

g.setColor(getBackground()); 
g.fillRect(0, 0, getWidth(), getHeight()); 
g.setColor(getForeground()); 

 

Układ  współrz

ę

dnych  komponentu

  –  współrz

ę

dne  całkowite  z  zakresu 

(0, 0) do (szeroko

ść

 - 1, wysoko

ść

 - 1). 

 

Ewentualne obramowanie zmniejsza obszar malowania komponentu. 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 21 

 

Informacj

ę

 o komponencie uzyskujemy za pomoc

ą

 metod: 

getWidthgetHeight

 i 

getInsets

 (dla informacji o brzegu). 

Np.  

public void paintComponent(Graphics g) { 
    ... 
    Insets insets = getInsets(); 
    int currentWidth = getWidth() - insets.left - insets.right; 
    int currentHeight = getHeight() - insets.top - insets.bottom; 
    ... 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 22 

4) Metoda 

repaint

 

Argumenty metody 

repaint

  

void repaint()  

nakaz odmalowania całego obszaru komponentu. 

void  repaint(int,  int,  int,  int) 

–  nakaz  odmalowania  jedynie  podanego 

obszaru prostok

ą

tnego w komponencie - X, Y, szeroko

ść

, wysoko

ść

 
Przykład 10.2

 Program obliczaj

ą

cy obszar dla odmalowania. 

 

class SelectionArea extends JLabel { 
    ... 
    public SelectionArea(ImageIcon image, ...) { 
        super(image); 

// Komponent wy

ś

wietla obraz.

  

        ... 
    } 

    ...// W obsłudze zdarzenia „mouse-dragged”: 

        Rectangle totalRepaint = rectToDraw.union(previousRectDrawn); 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 23 

        repaint(totalRepaint.x, totalRepaint.y, 
                totalRepaint.width, totalRepaint.height); 

    ... 
    public void paintComponent(Graphics g) { 

        

super.paintComponent(g);

 

// Maluje tło i obraz 

        ... 

        // Maluje prostok

ą

t na obrazie. 

        g.setColor(Color.white); 
        g.drawRect(rectToDraw.x, rectToDraw.y, 
                   rectToDraw.width - 1, rectToDraw.height - 1); 
        ... 
    } 
    ... 

Nad  obrazem  malowana  jest  ramka  wybrana  przez  u

Ŝ

ytkownika.  Tylko 

obszar komponentu odpowiadaj

ą

cy tej ramce jest odmalowywany. 

 

Ten sam prostok

ą

t przekazany do metody 

repaint

 odzwierciedlony jest w 

obiekcie 

Graphics 

przekazanym do metody 

paintComponent.

 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 24 

Metoda 

getClipBounds

 umo

Ŝ

liwia pobranie malowanego obszaru: 

public void paintComponent(Graphics g) { 
    Rectangle clipRect = g.getClipBounds(); 
    if (clipRect != null) { 

 

// punkt odniesienia  

= (clipRect.x, clipRect.y)

 

 

// szeroko

ść

, wysoko

ść

  

= clipRect.width, clipRect.height

 

    } else {  ...   } 

Obiekt 

Graphics

  

Obiekt 

Graphics

 zawiera informacje (stan kontekstu graficznego – kolor, 

czcionk

ę

,  obszar  malowania)  i  metody  potrzebne  do  malowania  (np. 

drawImage, drawString, drawRect, fillRect).  

Ustawianie i pobieranie kontekstu, np. 

getColor, getFont, setColor, setFont, setClip, getClipBounds

 
Po  zredukowanym  malowaniu  nale

Ŝ

y  odtworzy

ć

  obszar  malowania 

komponentu jeszcze w metodzie 

paintComponent

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 25 

Rectangle oldClipBounds = g.getClipBounds(); 
Rectangle clipBounds = new Rectangle(...); 
g.setClip(clipBounds); 

...// Malowanie ... 

g.setClip(oldClipBounds);

 

// Odtworzenie obszaru malowania

 

 
Powy

Ŝ

sze  wynika  z  faktu, 

Ŝ

e  nie  mamy  pełnej  kontroli  nad  obszarem 

malowania w programie: 

-

  wiele  kolejnych  wywoła

ń

 

repaint

  mo

Ŝ

e  by

ć

  poł

ą

czonych  w  jedno 

wywołanie 

paintComponent;

 

-

  metoda 

paintComponent

  mo

Ŝ

e  by

ć

  wołana  przez  domy

ś

lny  system 

malowania,  bez  jawnego  wołania  w  aplikacji 

repaint

;  np.  pierwsza 

prezentacja  GUI,  odsłoni

ę

cie  okna  komponentu  przez  zabranie 

innego przesłaniaj

ą

cego okna. 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 26 

10.3 Wzorce projektowe 

Composite

 i 

Decorator

 

1) Wzorzec struktury 

Composite

 

Composite

  jest  wzorcem  słu

Ŝą

cym  do  reprezentacji 

struktur  drzewiastych  typu 

cało

ść

-cz

ęść

  w  taki  sposób,  aby  sposób  zarz

ą

dzania  struktur

ą

  nie  zale

Ŝ

ał  od 

jej  zło

Ŝ

ono

ś

ci.  Ten  wzorzec  jest  implementowany  w 

obiektowych  bibliotekach 

AWT i Swing

 do realizacji struktury „komponent – kontener” i do zarz

ą

dzania jej 

wizualizacj

ą

 
Z  punktu  widzenia  obiektu-klienta  wzorzec 

Composite

  umo

Ŝ

liwia  zarz

ą

dzanie 

cało

ś

ci

ą

 za pomoc

ą

 wywołania operacji dla 

jednego obiektu – korzenia drzewa

Niepotrzebna  jest  mu  wiedza  o  rozmiarze  drzewa,  poniewa

Ŝ

  wywołanie 

operacji  (np.  odmalowania  kontenera)  zostanie  przekazane  automatycznie  do 
wszystkich jego elementów. 
 
Centralnym  elementem  wzorca  jest 

interfejs 

Component

,  który  reprezentuje 

dowolny  obiekt  w  strukturze  drzewiastej.  Posiada  on  mo

Ŝ

liwo

ś

ci  dodawania  i 

usuwania  swojego  obiektu  potomnego  (oczywi

ś

cie,  tak

Ŝ

e  typu 

Component

oraz  odwołania  si

ę

  do  wybranego  potomka.  Zawiera  on  tak

Ŝ

metod

ę

 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 27 

operation()

, któr

ą

 nale

Ŝ

y wykona

ć

 na ka

Ŝ

dym w

ęź

le struktury. 

 

 

Interfejs 

Component

 posiada dwie implementacje: 

Leaf

 oraz 

Composite

Klasa 

Leaf

  reprezentuje  obiekty,  które  nie  posiadaj

ą

  potomków  (czyli  li

ś

cie  w 

strukturze), 

natomiast 

Composite

 jest dowolnym w

ę

złem po

ś

rednim. 

 
Poniewa

Ŝ

  ka

Ŝ

dy  w

ę

zeł  po

ś

redni  zarz

ą

dza  tak

Ŝ

e  poddrzewem,  którego  jest 

korzeniem, 

dlatego 

metoda 

operation()

poza 

wykonaniem 

operacji 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 28 

specyficznych  dla  ka

Ŝ

dego  w

ę

zła,  wywołuje  swoje  odpowiedniki  w  obiektach 

potomnych, w ten sposób propaguj

ą

c wywołanie. 

 

2) Wzorzec struktury 

Decorator

 

Celem  wzorca  jest  u

mo

Ŝ

liwienie 

dynamicznego

  dodawania  funkcjonalno

ś

ci  do 

obiektu.  Stwarza  on 

elastyczn

ą

  alternatyw

ę

  dla  mechanizmu  dziedziczenia 

klas. 

 

 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 29 

Klient 

wysyła  komunikat  do  obiektu 

Decorator

,  który  przekazuje  go  obiektowi 

ConcreteComponent

 i wykonuje 

dodatkowe operacje

 

(„dekoracje”).

 

 
Component 

jest  wspólnym  interfejsem 

dla  wszystkich  klas,  które  mo

Ŝ

na 

dekorowa

ć

.  Implementuj

ą

  go  zarówno  klasa 

ConcreteComponent

,  która  jest 

odpowiedzialna  za  podstawow

ą

  funkcjonalno

ść

  oferowan

ą

  klientowi,  jak  i 

dekoratory

.  

 

Ka

Ŝ

dy  dekorator

  posiada  referencj

ę

  (oznaczon

ą

  jako  kompozycj

ę

,  aby 

zaznaczy

ć

  obowi

ą

zkowo

ść

  i  sił

ę

  tej  relacji)  do  innego  obiektu 

Component

którym  mo

Ŝ

e  by

ć

  ponownie  dekorator  lub 

ConcreteComponent

.  Otrzymuj

ą

Ŝą

danie  wykonania  okre

ś

lonej  operacji, 

dekorator  deleguje  je

  do  swojego 

„wewn

ę

trznego”  obiektu 

Component

,  a  nast

ę

pnie  wykonuje 

specyficzn

ą

  dla 

siebie dodatkow

ą

 

funkcjonalno

ść

 

Czyli  dodanie  do  obiektu  nowej  funkcjonalno

ś

ci

  polega  na  utworzeniu 

dekoratora i przekazaniu mu tego obiektu.  
 
Kiedy  ka

Ŝ

dy  dekorator  (klasy 

ConcreteDecoratorA

  i 

ConcreteDecoratorB

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 30 

dodaje  do  dekorowanego  obiektu  tylko  jedn

ą

  funkcj

ę

,  wówczas  dekoruj

ą

obiekt  wielokrotnie  uzyskujemy  efekt  osi

ą

gni

ę

cia 

Ŝą

danej  sumarycznej 

funkcjonalno

ś

ci.  

 
Pod  wzgl

ę

dem  typu  udekorowany  obiekt  nie  ró

Ŝ

ni  si

ę

  od  obiektu 

nieudekorowanego  (klient  widzi  go  przez  interfejs 

Component

),  dlatego 

zastosowanie tego wzorca nie wymaga istotnych zmian w kodzie klienta. 
 
Obiekt 

ConcreteComponent

,  aby  mógł  uczestniczy

ć

  w  tym  wzorcu,  musi 

definiowa

ć

  interfejs 

Component

,  którego  alternatywn

ą

  implementacj

ą

  s

ą

 

dekoratory.  
Wa

Ŝ

ne  jest  te

Ŝ

,  aby  dekoratory  odpowiednio  delegowały  swoje  metody  do 

wewn

ę

trznych obiektów typu 

Component

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 31 

10.4 W

ą

tek rozdziału zdarze

ń

 

1) "Event-dispatching thread" 



 Kod 

obsługi  zdarze

ń

  wykonywany  jest  zawsze  w  jednym  w

ą

tku,  tzw. 

w

ą

tku  rozdziału  zdarze

ń

  ("

event-dispatching  thread

").  Dzi

ę

ki  temu 

Ŝ

adna  obsługa  zdarzenia  w  programie  nie  mo

Ŝ

e  si

ę

  rozpocz

ąć

  zanim 

nie  zako

ń

czy  si

ę

  obsługa  poprzedniego  zdarzenia.  Np.  kod  metody 

actionPerformed

 wykonuje si

ę

 w w

ą

tku rozdziału zdarze

ń

 



 

Równie

Ŝ

 kod 

malowania komponentów

 na ekranie wykonuje si

ę

 w tym 

unikalnym 

w

ą

tku rozdziału zdarze

ń

. Czyli od

ś

wie

Ŝ

anie komponentu nie 

mo

Ŝ

e si

ę

 odby

ć

 dopóki wykonywana jest obsługa zdarzenia wcze

ś

niej 

zainicjalizowana ni

Ŝ

 nakaz od

ś

wie

Ŝ

enia wygl

ą

du komponentu GUI. 

 

Zasady współpracy programu z GUI  



 Dla 

apletu

 nale

Ŝ

y konstruowa

ć

 GUI w metodzie 

init

( )



 Dla 

aplikacji 

bezpieczne jest stosowanie nast

ę

puj

ą

cego schematu: 

public class MyApplication { 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 32 

    public static void main(String[] args) { 
        JFrame f = new JFrame(...); 

        ...// Dodaj komponenty do ramki.. 

        f.pack();  

// Realizuj ramk

ę

 

        f.setVisible(true); 

// Wy

ś

wietl ramk

ę

 

        // Teraz nie konstruuj ju

Ŝ

 

Ŝ

adnych elementów GUI. 

    } 

    // Wszystkie operacje na GUI - np. 

setText, getText

, itd.  

    // wykonywane s

ą

 podczas obsługi zdarze

ń

, np. 

actionPerformed().

 

    ... 

Stosuj zasad

ę

 pojedynczego w

ą

tku 

"Po realizacji komponentu Swing-a ka

Ŝ

dy kod w programie, który zale

Ŝ

od  stanu  komponentu  lub  wpływa  na  zmian

ę

  stanu  komponentu 

powinien by

ć

 wykonywany w w

ą

tku rozdziału zdarze

ń

." 

 
Realizacja  komponentu

  oznacza, 

Ŝ

e  jest  on  przygotowany  do 

namalowania go na ekranie.  

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 33 



 

Realizacja  głównego  okna

  nast

ą

pi  na  skutek  wywołania  dla  niego 

jednej z metod: 

setVisible(true),  
show(),  
pack().  



 Po realizacji okna jego 

komponenty s

ą

 te

Ŝ

 zrealizowane



 Je

ś

li 

dodajemy  komponent

  do  zrealizowanego  kontenera  to 

automatycznie nast

ę

puje 

realizacja tego komponentu

.  

Pierwsza realizacja ramki zwykle polega na wywołaniu 

pack

Nast

ę

pnie ramka jest wy

ś

wietlana wywołaniem 

setVisible

 (lub 

show

).  

 

Odst

ę

pstwa od zasady jednego w

ą

tku: 



 Pewne 

metody  w  API

 

s

ą

  zabezpieczone

  przed  w

ą

tkami  –  maj

ą

 

wbudowan

ą

 synchronizacj

ę

 dost

ę

pu.  



 

GUI aplikacji

 mo

Ŝ

e by

ć

 skonstruowany, zrealizowany i wy

ś

wietlony po 

raz pierwszy w 

głównym w

ą

tku

.  

Przypomnijmy poprzedni przykład: 

public static void main(String[] args) {  

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 34 

    JFrame f = new JFrame(...); 

    ...// Dodaj komponenty do ramki ... 

    f.pack(); 
    f.setVisible(true); 

    // Dalej nie definiuj wi

ę

cej GUI . 

}  

W tym przykładzie GUI skonstruowano 

w głównym w

ą

tku

. Mo

Ŝ

liwe jest 

bowiem  skonstruowanie  (ale  nie  wy

ś

wietlenie)  GUI  w  dowolnym 

w

ą

tku,  je

ś

li  tylko  nie  ma  w  nim  odwoła

ń

  do  (lub  modyfikacji)  ju

Ŝ

 

"zrealizowanych" komponentów.  
Teoretycznie  wywołanie 

setVisible

 

nie  jest  zabezpieczone  przed 

w

ą

tkami

, gdy

Ŝ

 komponenty zostały wła

ś

nie zrealizowane wywołaniem 

pack

. Jednak je

ś

li program nie posiada jeszcze widocznego GUI, jest 

mało  prawdopodobne,  aby  nast

ą

piło  wywołanie 

paint

  zanim  metoda 

setVisible

 powróci. 

 

 


 

GUI apletu

 mo

Ŝ

e by

ć

 skonstruowany i wy

ś

wietlony w 

metodzie 

init

.  

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 35 

Przegl

ą

darki nie wołaj

ą

 

paint 

dla apletu zanim nie wykonaj

ą

 si

ę

 metody 

init

  i 

start

.  Dlatego  bezpieczne  jest  skonstruowanie  GUI  w  metodzie 

apletu 

init

, je

ś

li tylko nie wywołuje si

ę

 w niej 

show()

 lub 

setVisible(true)

 

dla obiektu apletu.  

 


 

Metody  klasy 

JComponent

 

repaint

  i 

revalidate

  -  mog

ą

  by

ć

  wołane  z 

ka

Ŝ

dego  w

ą

tku.  Te  metody  przekazuj

ą

  swoje  wywołania  do  kolejki 

obsług dla w

ą

tku rozdziału zdarze

ń

 



 

Listy  z  obserwatorami  zdarze

ń

  mog

ą

  by

ć

  modyfikowane  przez  ka

Ŝ

dy 

w

ą

tek  -  mo

Ŝ

na  wsz

ę

dzie  wywoła

ć

  metody 

addListenerTypeListener

  i 

removeListenerTypeListener

 – te operacje nie maj

ą

 wpływu na aktualnie 

realizowany rozdział zdarze

ń

 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 36 

2) Jak nale

Ŝ

y wykonywa

ć

 kod w 

w

ą

tku rozdziału zdarze

ń

Operacje  na  GUI  po  jego  inicjalizacji  prowadzone  s

ą

  przez  w

ą

tek 

rozdziału  zdarze

ń

.  Programy  sterowane  s

ą

  zdarzeniami  pochodz

ą

cymi 

od widocznych komponentów takich jak przyciski lub operacje mysz

ą

 
Jednak  s

ą

  te

Ŝ

  sytuacje,  gdy  program  wykonuje  operacje  na  GUI,  które 

nie s

ą

 inicjowane zdarzeniami. Oto przykłady takich sytuacji. 

 

- Program wykonuje dłu

Ŝ

sz

ą

 inicjalizacj

ę

 „na raty” 

Taki program zwykle tworzy i pokazuje "zacz

ą

tki" swojego GUI podczas 

inicjalizacji, a potem prowadzi zmian

ę

 i modyfikacj

ę

 swojego GUI. 

Uzupełniaj

ą

ca  inicjalizacja  nie  powinna  mie

ć

  miejsca  w  w

ą

tku  rozdziału 

zdarze

ń

, gdy

Ŝ

 blokowałaby przyjmowanie zdarze

ń

 i od

ś

wie

Ŝ

anie ekranu 

dla programu.  
 

-  Programy,  których  GUI  musi  by

ć

  zmodyfikowany  w  wyniku 

niestandardowych zdarze

ń

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 37 

Np.  metoda  programu  serwera  mo

Ŝ

e  zosta

ć

  wywołana  przez  nieznany 

w

ą

tek  wykonywany  na  innej  maszynie.  Jednak  w  celu  modyfikacji  GUI 

metoda  ta  powinna  wywoła

ć

  kod  wykonywany  w  w

ą

tku  rozdziału 

zdarze

ń

 

3) 

Asynchroniczne wywołania

 metod w w

ą

tku rozdziału zdarze

ń

 

Klasa 

SwingUtilities

  posiada  2  metody  przeznaczone 

do  współpracy 

programu z w

ą

tkiem rozdziału zdarze

ń

:

  



 

invokeLater  

Metoda  spowoduje  wykonanie  zadanego  kodu  w  w

ą

tku  rozdziału 

zdarze

ń

.  Metoda  nie  czeka  na  wykonanie  si

ę

  tego  kodu  lecz  powraca 

natychmiast. 



 

invokeAndWait  

Działa  podobnie  jak  metoda 

invokeLater

  ale  czeka  na  wykonanie  si

ę

 

zadanego kodu. 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 38 

Deklaracja metody 

invokeLater( )

 

public static void invokeLater(Runnable doRun

Powoduje  asynchroniczne  wykonanie  metody 

doRun.run()

  w  w

ą

tku 

rozdziału 

zdarze

ń

po 

wcze

ś

niejszym 

wykonaniu 

wszystkich 

oczekuj

ą

cych w kolejce metod obsługi zdarze

ń

.  

Ta metoda 

mo

Ŝ

e by

ć

 te

Ŝ

 wołana

 z samego w

ą

tku rozdziału zdarze

ń

.  

Za  obsług

ę

  ewentualnych 

wyj

ą

tków

  zgłaszanych  podczas  wykonania 

zleconego zadania 

odpowiada w

ą

tek rozdziału zdarze

ń

 

Przykład

. Wywołanie zadania obiektu 

doHelloWorld

 i wydruk komunikatu: 

 

Runnable doHelloWorld = new Runnable() { 

     public void run() { 
         System.out.println("Hello World w " + Thread.currentThread()); 
     } 

 }; 
… 
 SwingUtilities.invokeLater(doHelloWorld); 

// Wykonaj później 

 System.out.println("Ten komunikat moŜe pojawić się wcześniej niŜ górny."); 

background image

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 39 

Deklaracja metody 

invokeAndWait( ) 

public static void invokeAndWait(Runnable doRun
                          throws InterruptedExceptionInvocationTargetException 

Tak

Ŝ

e  ta  metoda  powoduje  asynchroniczne  wykonanie  metody 

doRun.run()

  w  w

ą

tku  rozdziału  zdarze

ń

,  po  wcze

ś

niejszym  wykonaniu 

wszystkich  oczekuj

ą

cych  w  kolejce  metod  obsługi  zdarze

ń

.  Jednak 

wołaj

ą

ca metoda 

zostaje zablokowana

 w oczekiwaniu na wykonanie si

ę

 

zleconego zadania.  
Metody 

invokeAndWait()

 

nie mo

Ŝ

na

 wywoła

ć

 w w

ą

tku rozdziału zdarze

ń

Przykład.

 

Wywołanie metody 

invokeAndWait()

 z nowo tworzonego w

ą

tku 

w  aplikacji  w  celu  wypisania  napisu  w  w

ą

tku  rozdziału  zdarze

ń

,  a 

nast

ę

pnie  po  powrocie  metody  nast

ę

puje  wypisanie  pochodz

ą

ce  z 

nowego w

ą

tku aplikacji. 

final Runnable doHelloWorld = new Runnable() { 
     public void run() { 
         System.out.println("Hello World w " + Thread.currentThread()); 
     } 
 }; 

10. Swing – układanie i malowanie 

W. Kasprzak: Programowanie zdarzeniowe 

10 - 40 

 Thread appThread = new Thread() { 
     public void run() { 
         try {    SwingUtilities.invokeAndWait(doHelloWorld); 
         } 
         catch (Exception e) {    e.printStackTrace(); 
         } 
         System.out.println("Koniec w " + Thread.currentThread()); 
     } 
 }; 
… 
 appThread.start(); 

Je

ś

li  metoda 

run()

  wołanego  obiektu  implementuj

ą

cego 

Runnable

 

zgłasza wyj

ą

tek nieobsługiwany przez w

ą

tek rozdziału zdarze

ń

 to jest on 

zamieniany  na  wyj

ą

tek  typu 

InvocationTargetException

  i  przekazywany 

do obsługi przez wołaj

ą

cy w

ą

tek. 

Wyj

ą

tek  typu 

InterruptedException

  zgłaszany  jest  wtedy,  gdy 

oczekiwanie  naszego  w

ą

tku  na  zako

ń

czenie  si

ę

  zleconego  zadania 

zostaje przerwane.