Crearea interfetelor grafice. Pachetul java.awt
-
Introducere
-
Componente grafice
-
Ierarhia claselor pentru
componente
-
Obiecte peer
-
Conceptul Model/View/Controller
(MVC)
-
Afisarea componentelor
-
Organizarea componentelor
Introducere
Acest pachet ne ofera o coletie de clase pentru crearea
interfetelor grafice. Aceste clase permit lucrul cu ferestre, desenari,
lucrul cu imagini si utilizarea componentelor ca butoane, liste, meniuri
intr-un mod independent de platforma. Pachetul java.awt contine clasele
AWT (Abstract Window Toolkit) GUI iar java.awt.image ne ofera niste facilitati
in plus pentru lucrul cu imagini. Dupa cum numele sugereaza AWT este o
abstractie. Clasele si functionalitatile oferite sunt aceleasi pentru orice
implementare Java. Pentru a obtine independenta de platforma AWT utilizeaza
toolkituri interschimbabile care actioneaza cu sistemul de ferestre pe
care se ruleaza aplicatia. De exemplu sa presupunem ca aplicatia noastra
creaza un buton. Cand se ruleaza aplicatia, toolkitul specific platformei
afiseaza butonul conform platformei. Daca aplicatia se ruleaza sub Windows
vom obtine un buton de tip Windows, iar daca se ruleaza sub Unix
se va afisa un buton de tip X Windows.
Utilizarea componentelor din acest pachet este relativ
usoara, pe cand toolkiturile GUI sunt foarte complexe, dar aceasta este
treaba celor care vor sa implementeze AWT-ul pe o noua platforma.
Realitatea este ca cele mai multe probleme despre Java se ridica la
folosirea acestui pachet. Implementarea toolkiturilor pentru acest pachet
contin cele mai multe buguri Java. Tocmai din aceasta cauza JavaSoft a
introdus Swing care reprezinta noua generatie de componentele grafice si
fac parte din JFC (Java Foundation Classes).
Componente grafice
Componentele sunt elementele care se utilizeaza la crearea unei interfete
grafice. Componentele sunt incluse in containere, care la randul lor sunt
componente speciale. Anumite componente pot fi containere pentru alte componente:
de exemplu o fereastra cu doua panouri. In acest caz fereastra este containerul,
iar panelele sunt componentele continute. Daca adaugam elemente ca butoane,
liste, etichete, casete text etc. in cele doua panouri atunci panoul va
fi containerul iar elementele adaugate vor fi componentele.

Ierarhia claselor
pentru componente
Pentru simplitate impartim functionalitatea clasei Component
in doua categorii: modul de afisare si comportament. Aceasta
clasa contine metode si variabile care controleaza modul de afisare general
al componentei. Aici sunt incluse atributele pentru vizibilitate, marime,
pozitie si atribute ca culoarea si fontul. Clasa contine metode abstracte,
care sunt implementate de subclasele pentru diferite tipuri de componente,
si care determina imaginea grafica a componentei. Prin comportamentul componentei
intelegem actiunile componentei la evenimentele primite de la utilizator.
In momentul cand utilizatorul actiuneaza asupra unei componente (de exemplu
apsa butonul mouse-ului) un fir de executie AWT informeaza toti receptorii
(componentele care vor sa primeasca acest eveniment) despre evenimentul
produs. De exemplu la apasarea unui buton se genereaza evenimentul ActionEvent.
Cei
care vor sa primeasca acest eveniment trebuie sa fie inregistrati, aceasta
insemnand ca trebuie sa fie obiecte care respecta interfata ActionListener.
Evenimentele sunt receptionate de catre obiecte
de tip Listener, care la primirea evenimentului apeleaza o metoda de tratare
a evenimetului. Obiectele care doresc sa primeasca evenimente trebuie sa
implementeze interfetele pentru tipurile de evenimente pe care doresc sa
le primeasca. De exemplu evenimentele de tip MouseEvents sunt primite de
catre obiectele care respecta interfata MouseListener. Evenimentele reprezinta
un mecanism de comunicare intre obiecte (nu numai obiecte grafice). Evenimentele
sunt importante mai alesin cazul beanurilor Java.
Containerele rezolva tratarea evenimentelor pentru
toate componentele continute. De obicei containerul se inregistreaza la
sursa de evenimente pentru a primi evenimentele necesare pentru o anumita
componenta.
Peer
In sectiunea precedenta tocmai am descris functionarea acestor componente
si evenimentele cu ajutorul carora aceste componente comunica intre ele.
Asa sunt privite componentele de Java, dar nu si in lumea reala, adica
pe platforma pe care vor fi efectiv afisate componentele. Lumea reala este
caracterizata de o anumita arhitectura si de dispozitive fizice. La un
anumit nivel obiectele noastre vor comunica cu obiecte care contin metode
native pentru mediul in caare componentele trebuie sa interactioneze.
Pentru a tine aceasta interactiune sub control Java utilizeaza interfetele
peer.
Aceasta interfata peer face posibila ca o componenta AWT Java sa
utilizeze componenta corespunzatoare din lumea reala - obiectul peer
din mediul nativ. Programele noastre vor lucra cu obiectele AWT Java, restul,
partea grea este rezolvata de clasa Component.
Este important sa intelegem aceasta arhitectura deoarece
astfel putem intelege cam ce putem realiza cu componentele. In figura preceedenta
se poate vedea ce se intampla la crearea unui buton. Toolkitul este de
fapt o "fabrica de componente" native. Java utilizeaza aceasta fabrica
pentru a separa funtionalitatea componentelor de modalitatea de implementare
pe un sistem de afisare nativ. Obiectul Toolkit contine metode pentru crearea
tuturor tipurilor de componente grafice. Daca nu ne place acest Toolkit
oferit de mediul Java, putem sa scriem toolkitul nostru propriu.
Pachetul java.awt.peer contine o interfata pentru
fiecare tip de componenta grafica. In acest pachet clasa de baza este ComponentPeer
de la care se deriva aproape toate celelalte clase. De exemplu clasei Button
ii corespunde clasa ButtonPeer. Apelul metodei setLabel() determina
apelul metodei corespunzatoare al obiectului nativ.

Conceptul Model/View/Controller
(MVC)
MVC este o metoda pentru producerea componentelor reutilizabile
care sunt caracterizate prin structura, reprezentare si comportament. MVC
a fost introdus ca standard in primul rand pentru componentele grafice,
dar ideile de baza pot fi aplicate si la alte tipuri de componente. Ideea
fundamentala este separarea modelului de reprezentare. Pentru un singur
model de date exista mai multe reprezentari diferite. De exemplu datelor
dintr-un spreadsheet putem atasa diferite tipuri de grafice. In cazul unei
componente de tip Button modelul de date ar fi o valoare logica
pentru a reprezenta starea butonului, reprezentarea este modul de
afisare, aspectul grafic al butonului, iar evenimentele reprezinta partea
de control.
Comunicarea intre componentele grafice AWT respecta
MVC. Receptorii evenimentelor sunt Observatori iar sursele
evenimentelor Observabili. In momentul cand un obiect Observabil
isi modifica starea informeaza toti observatorii despre aceasta modificare.
Conceptul "fabrica de componente" utilizat de catre
obiectul Toolkit respecta tot MVC. Aceste "fabrici" utilizeaza interfetele
Java pentru a separa implementarea obiectelor grafice de comportamentul
acestora. Componetele native trebuie sa respecte doar anumite interfete,
nu trebuie sa se incadreze intr-o ierarhie de clase. Singurul lucru pe
care trebuie sa-l faca este implementarea metodelor din interfata.
Afisarea componentelor
Componetele pot fi rugate sa se autoafiseze. De exemplu daca fereastra
care contine componentele este acoperita de o alta fereastra, in momentul
revenirii la fereastra initiala aceasta trebuie reafisata cel putin partial.
Cand AWT roaga componenta sa se autoafiseze, aceasta apeleaza metoda paint().
Metoda update() are aceasi functionalitae, dar aceasta prima data
sterge suprafata componentei si dupa aceea apeleaz metoda paint(). Componentele
nu vor apela direct update(), aceasta metoda fiind apelata de catre repaint().
Aceasta metoda roaga AWT sa programeze componenta in cauza pentru improspatare.
Atat paint() cat si update() au un parametru de tip Graphics care reprezinta
contextul grafic a componentei in cauza. Corespunde suprafetei ecran pe
care componenta poate desena. Acesta este mecanismul utilizat de componente
pentru autoafisare. Noi vom utiliza aceste metode doar in cazul containerelor
speciale, adica in cazul obiectelor de tip Panel, Canvas si Applet.
Organizarea componentelor
Un organizator al componentelor este un obiect care stabileste marimea
si pozitia componentelor in cadrul unui container. Fiecare container are
un organizator implicit care in caz de necesitate poate fi modificat. Containerele
principale sunt diferitele tipuri de ferestre, apleturi, panele etc. In
cazul ferestrelor organizatorul implicit este un obiect de tip BorderLayout,
iar in cazul apleturilor si ale panourilor unul de tip FlowLayout. Clasele
principale organizatori de componente sunt: FlowLayot, GridLayout,CardLayout,
BorderLayout si GridBagLayout.

FlowLayout organizeaza componentele de la stanga la dreapta si
daca se umple randul curent atunci componetul urmator va fi plasat in randul
urmator. Inaltimea randului este data de componenta de cea mai mare inaltime
pe randul respectiv.
FlowLayout fLayout = new FlowLayout();
setLayout( fLayout );
Button butonOk = new Button("Ok");
add(butonOk);
Button butonCancel = new Button("Cancel");
add(butonCancel);
sau scris mai compact:
setLayout( new FlowLayout());
add( new Button("Ok"));
add( new Button("Cancel"));
Organizatorul centreaza componentele adaugate, dar acest tip de
aliniere poate fi schimbata prin metoda setAlignment(). Metoda primeste
ca parametru tipul alinierii. Tipurile de aliniere posibile sunt definite
ca constante in clasa FlowLayout (LEFT, RIGHT, CENTER) si se utilizeaza
in modul urmator:
FlowLayout fLayout = new FlowLayout();
fLayout.setAlignment(FlowLayout.LEFT)
setLayout( fLayout );
BorderLayout aranjeaza componentele in cinci regiuni: Nord,
Sud, Vest, Est si Centru. La adaugarea componentelor utilizand acest organizator
trebuie specificat pe langa componenta adaugata si regiunea la care se
adauga. Atat BorderLayout cat si CardLayout permite specificarea spatiului
intre componente indicand numarul de pixeli pe orizontala respectiv pe
verticala.
setLayout( new BorderLayout(), 10,6);
add( new Button("Unu"),"North");
add( new Button("Doi"),"East");
add( new Button("Trei"),"South");
add( new Button("Patru"),"West");
CardLayout (teanc de carti) se utilizeaza la organizarea
componentelor care nu incap pe o anumita suprafata. Componentele sunt organizate
pe aceste carti dintre care unul singurul se va vedea pe ecran. Visual
Caffe introduce ferestrele cu mai multe pagini care pot inlocui acest organizator.
GridLayout imparte suprafata in randuri si coloane permitand
aranjarea componentelor in aceste celule de dimensiuni egale. Componentele
sunt plasate in celule incepand cu primul rand dupa aceea urmatorul rand
si asa mai departe.
GridBagLayout este organizatorul cel mai avansat. Lucreaza asemanator
ca GridLayout. Principala diferenta fata de acesta este ca in caul acestui
organizator o componenta poate ocupa mai mult decat o singura celula.
Un container poate sa contina la randul lui alte containere si fiecare
dinntre aceste containere avand propriul organizator. De exemplu o fereastra
continand mai multe panele.