Documente Academic
Documente Profesional
Documente Cultură
Curs 10
MANAGEMENTUL UNEI INTERFETE GRAFICE
Aspectul de pana acum al unei interfete grafice AWT era oarecum relativ redimensionarea ferestrei putand modifica intreaga dispunere in fereastra . Aceasta
maleabilitate a interfetei grafice apare in Java datorita posibilitatii sale de a rula pe
diferite platforme care trateaza diferit elementele componente ale unei interfete
grafice .
Pentru a introduce un control mai strict asupra aspectului interfetei noastre Java ne
pune la dispozitie pentru pachetul AWT un numar de 5 administratori de dispunere .
DISPUNEREA COMPONENTELOR UNEI INTERFETE
Un administrator de dispunere determina modul in care vor fi aranjate componentele
unui contatiner . Administratorul implicit al Java este clasa FlowLayout . Ea permite
dispunerea secventiala a obiectelor , de la stanga la dreapta si de sus in jos .
Pachetul AWT poate folosi inca patru administratori : GridLayout , BorderLayout ,
CardLayout si GridBagLayout .
Pentru a crea un administrator pentru un container se creaza o instanta a clasei
container folosind o instructiune de tipul :
FlowLayout administrator=new FlowLayout();
Acest administrator nou creat trebuie apoi declarat ca administrator pentru container
cu ajutorul metodei setLayout() . Administratorul de dispunere trebuie stabilit inainte
de a adauga componente containerului . Daca nu este stabilit un administrator explicit
atunci apare automat cel de dispunere secventiala ( FlowLayout ) .
In exemplul de mai jos avem inceputul unui applet care foloseste un administrator de
dispunere :
public class Inceput extends java.applet.Applet {
FlowLayout ad=new FlowLayout();
public void init() {
setLayout(ad);
}
}
ADMINISTRATORUL DE DISPUNERE SECVENTIALA ( FlowLayout )
Daca foloism constructorul FlowLayout() fara argumente toate componentele de pe
fiecare rand vor fi automat centrate . Daca vrem ca alinierea sa se faca explicit trebuie
sa utilizam ca argument pentru constructor una dintre variabilele de clasa
FlowLayout.LEFT sau FlowLayout.RIGHT sau chiar FlowLayout.CENTER .
add(b5);
add(b6);
add(b7);
add(b8);
add(b9);
}
}
ADMINISTRATORUL DE DISPUNERE MARGINALA ( BorderLayout )
Administratorul BorderLayout imparte un container in 5 zone : nord , sud , est , vest si
centru . In cadrul acestei dispuneri componentele din cele patru directi de baza vor
ocupa spatiul pe care il necesita iar centrul va primi restul de spatiu .
Exista doua versiuni ale constructorului clasei BorderLayout : fara nici un parametru
sau cu doi parametri . Prima varianta creaza o dispunere fara spatiere intre
componente in timp ce a doua varianta permite specificarea distantei in pixeli pe
orizontala si pe verticala dintre componente .
Dupa crearea si aplicarea administratorului de acest tip adaugarea componentelor in
container se face cu o metoda de genul :
add(string, componenta);
Primul argument are valori intre : "North" , "South" , "East" , "West" si "Center" . Al
doilea argument este chiar componenta care trebuie adaugata .
Programul de mai jos implementeaza un administrator de dispunere marginala :
import java.awt.*;
public class Margini extends java.applet.Applet {
BorderLayout b=new BorderLayout(10,15);
Button nord=new Button("Nord");
Button sud=new Button("Sud");
Button est=new Button("Est");
Button vest=new Button("Vest");
Button centru=new Button("Centru");
public void init() {
setLayout(b);
add("North",nord);
add("South",sud);
add("East",est);
add("West",vest);
add("Center",centru);
}
}
COMBINAREA ADMINISTRATORILOR DE DISPUNERE
Pentru a realiza o interfata grafica practica si utila trebuie de fapt sa folosim mai multi
administratori pentru aceeasi interfata . Acest lucru se poate face adaugand mai multe
containere intr-un container principal , ca fereastra applet , fiecare avand un alt
administrator de dispunere .
Aceste containere mai mici se numesc panouri si sunt derivate din clasa Panel .
Panourile sunt folosite pentru a grupa diferite componente . Atunci cand lucram cu ele
trebuie sa retinem cateva lucruri :
-
import java.awt.*;
public class Carduri extends java.applet.Applet implements Runnable {
CardLayout cartela=new CardLayout();
Label[] etichete=new Label[6];
int crt=0;
Thread executabil;
public void start() {
if (executabil==null) {
executabil=new Thread(this);
executabil.start();
}
}
public void stop() {
executabil=null;
}
public void init() {
etichete[0]=new Label("Textul 1");
etichete[1]=new Label("Urmeaza textul 2");
etichete[2]=new Label("Apoi textul 3");
etichete[3]=new Label("Dupa care vine textul 4");
etichete[4]=new Label("Urmat de textul 5");
etichete[5]=new Label("Si in final apare textul 6");
setLayout(cartela);
for (int i=0;i<6;i++)
add("Cartela "+i,etichete[i]);
}
public void run() {
Thread firExecutie=Thread.currentThread();
while (executabil==firExecutie) {
cartela.show(this,"Cartela "+crt);
crt++;
if (crt>5)
crt=0;
repaint();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {}
}
}
}
Aceasta parte se realizeaza pe hartie , unde vom schita interfata grafica . Fiecare
componenta a interfetei trebuie plasata intr-o celula separata - desi o componenta
poate ocupa mai multe celule .
Schita noastra sa presupunem ca este ceva de genul :
Nume
Parola
OK
La pasul urmator ar trebui sa tabelam deja interfata noastra etichetand celulele cu
coordonatele lor x , y :
0,0
0,1
0,2
1,0
Nume
Parola
1,1
OK
1,2
In aceasta etapa ne vom axa pe dispunere doar asa ca vom folosi doar niste butoane
care sa tina locul elementelor reale ce vor apare pe panou .
Pentru usurinta specificarii restrictiilor vom defini o metoda care preia mai multe
valori si stabileste restrictiile pentru aceastea . Metoda definireRestrictii() preia sapte
argumente : un obiect GridBagConstraints si sase intregi care reprezinta variabilele
gridx, gridy, gridwidth, gridheight, weightx si weighty .
Primele doua argumente reprezinta valorile coordonatelor celulei respective - in cazul
in care o componenta ocupa mai multe celule coordonatele date sunt cele ale celului
aflate cea mai in stanga-sus ca pozitie .
Urmatoarele doua argumente reprezinta numarul de celule pe care le ocupa
componenta : gridwidth pentru coloane si gridheight pentru linii .
Ultimele doua argumente sunt date pentru latimea si inaltimea celulei - ca proportii
din totalul pe orizontala respectiv verticala .
Pentru atribuirea restrictiilor unui obiect se foloseste metoda setConstraints() ; aceasta
preia doua argumente : componente si restrictiile acesteia . Dupa ce toate acestea s-au
realizat componenta poate fi adaugata in panou .
Crearea de fapt a dispunerii se face in metoda init() . Aici vom defini un administrator
de dispunere GridBagLayout si se creaza un obiect pentru restrictii .
La finalul acestei etape trebuie sa verificam aspectul functional al tabelului , daca are
numarul corect de linii si coloane , daca unele componente care ocupa mai multe
celule sunt prezentate corect si daca nu apar alte anomalii vizibile .
-
Aici mai apar restrictiile care sa aranjeze componentele in cadrul celulelor . Avem
doua astfel de restrictii : fill si anchor .
Restrictia fill determina - pentru componentele care se pot extinde in orice directie - in
ce directie se face aceasta extindere ( cum ar fi casetele de text sau butoanele ) .
Restrictia fill poate avea una dintre urmatoarele patru valori , definite drept variabile
de clasa in GridBagConstrints :
-
GridBagConstraints.NORTH
GridBagConstraints.NORTHEAST
GridBagConstraints.SOUTH
GridBagConstraints.SOUTHWEST
GridBagConstraints.EAST
GridBagConstraints.SOUTHEAST
GridBagConstraints.WEST
GridBagConstraints.NORTHWEST
GridBagConstraints.CENTER
In realitate aceasta etapa apare aproape totdeauna ; pentru ca totul sa arate perfect va
trebui sa mai facem anumite modificari ale unor restrictii de obicei .
In listingul de mai jos avem un exemplu complet de creare a unui applet care
implementeaza o interfata grafica similara celei prezentate in etapa intai a constructiei
teoretice a unei interfete ce foloseste un administrator de dispunere tabelara
neproportionala :
import java.awt.*;
public class NumeParola extends java.applet.Applet {
void definireRestrictii(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx,
int wy) {
gbc.gridx=gx;
gbc.gridy=gy;
gbc.gridwidth=gw;
gbc.gridheight=gh;
gbc.weightx=wx;
gbc.weighty=wy;
}
public void init() {
La executarea unui clid de mouse apar de fapt doua evenimente : mouse down , la
apasarea butonului si mouse up la eliberarea butonului mouseului .
Semnatura metodei pentru evenimentul mouse down este :
public boolean mouseDown(Event evt, int x, int y) {
...
}
Metoda - ca si mouseUp() de altfel - primeste trei argumente : evenimentul si
coordonatele x si y unde a aparut evenimentul .
Argumentul evt este o instanta a clasei Event . Toate evenimentele genereaza o
instanta a clasei Event care contine informatii privind locul si perioada cand a avut loc
evenimentul , tipul sau si alte informatii .
De exemplu putem crea o metoda care sa afiseze coordonatele punctului unde s-a
executat un clic de mouse :
public boolean mouseDown(Event evt, int x, int y) {
System.out.println("Mouse apasat la coordonatele "+x+" , "+y);
return true;
}
Trebuie metionat ca aceasta metoda returneaza o valoare booleana , spre deosebire de
majoritatea metodelor folosite pana acum . Valoarea de retur true sau false a unei
metode de tratare de evenimente determina daca o anumita componenta poate
intercepta evenimentul sau daca trebuie sa il transmita mai departe altor componente .
Regula este ca daca metoda intercepteaza si trateaza evenimentul ea trebuie sa
returneze true ; daca metoda ignora evenimentul ea trebuie sa returneze false pentru ca
celelalte componente ale interfetei sa aiba sansa de a trata ele evenimentul .
In listingul de mai jos vom vedea un applet care va trata apasarea mouseului - la
fiecare clic de mouse in fereastra este desenata o pata , pana la totalul de maxim 15
pete :
import java.awt.*;
public class Pete extends java.applet.Applet {
final int MAXPETE=15;
int xpete[]=new int[MAXPETE];
int ypete[]=new int[MAXPETE];
int pataCrt=0;
public void init() {
setBackground(Color.yellow);
}
public boolean mouseDown(Event evt, int x, int y) {
if (pataCrt<MAXPETE) {
adaugaPata(x,y);
return true;
}
else {
System.out.println("Prea multe pete");
return false;
}
}
void adaugaPata(int x, int y) {
xpete[pataCrt]=x;
ypete[pataCrt]=y;
pataCrt++;
repaint();
}
public void paint(Graphics ecran) {
ecran.setColor(Color.blue);
for (int i=0;i<pataCrt;i++) {
ecran.fillOval(xpete[i]-10,ypete[i]-10,20,20);
}
}
}
2. Dublu clicuri
Clasa Event din Java poseda o variabila denumita clickCount care pastreaza aceasta
informatie . clickCount este o variabila intreaga care contine numarul de clicuri
consecutive aparute - consecutivitatea este determinata de sistemul de operare sau de
hardwareul mouseului . In cazul in care vrem sa tratam ca evenimente clicuri multiple
trebuie sa testam valoarea variabilei sus amintite in corpul metodei noastre :
public boolean mouseDown(Event evt, int x, int y) {
switch (evt.clickCount) {
case 1: // clic simplu
case 2: // clic dublu
case 3: // clic triplu
}
}
Metoda mouseDown() este de fapt apelata pentru fiecare clic in parte .
Ca sa fie mai clar sa luam exemplul :
public boolean mouseDown(Event evt, int x, int y) {
System.out.println("Numar de clicuri : "+evt.clickCount);
return false;
}
Daca rulam un program care implementeaza aceasta metoda si executam un triplu clic
rezultatul obtinut va fi :
Numar de clicuri : 1
Numar de clicuri : 2
Numar de clicuri : 3
3. Miscarile mouseului
AWT defineste doua tipuri distincte de miscari ale mouseului : tragerea sa - miscarea
se face cu butonul semnificativ apasat , si miscarea simpla - cu butonul neapasat .
Evenimentele de mai sus sunt interceptate si tratate cu ajutorul metodelor
mouseDrag() si mouseMove() .
Metoda mouseMove() seamana mult cu metodele care tratau clicurile de mouse :
public boolean mouseMove(Event evt, int x, int y) {
...
}
Meotda mouseDrag() are o semnatura similara si mai trebuie sa mentionam ca in
ambele metode argumentele pentru coordonatele x si y reprezinta noua pozitie a
mouseului si nu cea initiala .
Metodele mouseEnter() si mouseExit() sunt apelate cand mouseul patrunde sau
paraseste un applet sau o portiune a acestuia . Ambele metode au semnaturi similare
cu cele intalnite mai inainte , coordonatele x si y referindu-se aici la puctul unde
mouseul a patruns sau respectiv a parasit appletul :
public boolean mouseEnter(Event evt, int x, int y) {
...
}
Pentru a utiliza aceste evenimente si a le trata vom prezenta un exemplu de applet care
traseaza linii drepte pe ecran prin tragerea mouseului dintr-un punct in altul . Numarul
de linii va fi restrictionat la 20 :
import java.awt.Graphics;
import java.awt.Color;
import java.awt.Event;
import java.awt.Point;
public class Linii extends java.applet.Applet {
final int MAXLINII=20;
Point inceput[]=new Point[MAXLINII];
Point finalul[]=new Point[MAXLINII];
Point pctInitial;
Point pctCurent;
int linieCrt=0;
public void init() {
setBackground(Color.white);
}