Sunteți pe pagina 1din 15

Programare Java

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 .

In mod automat administratorul de dispunere secventiala lasa un spatiu de trei pixeli


intre componente pe un rand si tot cate trei pixeli intre randuri . Daca vrem sa
modificam aceste caracteristici putem folosi un constructor de genul :
FlowLayout(int, int, int)
Acesta primeste ca argumente :
-

alinierea ( o variabila de clasa )


spatiul in pixeli dintre componente pe orizontala
spatiul in pixeli pe verticala intre linii

ADMINISTRATORUL DE DISPUNERE TABELARA ( GridLayout )


Acesta aranjeaza componentele intr-un tabel de randuri si coloane . Componentele
sunt adaugate incepand cu celula aflata cel mai in stanga pe primul rand si continuand
spre dreapta . In continuare se va trece la urmatoarea linie si tot asa mai departe .
Clasa care implementeaza acest administrator este GridLayout . Un constructor al
acestei clase primeste doua argumente : numarul de linii si numarul de coloane al
tabelului in care se va imparti containerul .
Exista si posibilitatea de a utiliza inca doua argumente care sa exprime spatiul pe
orizontala si pe verticala intre componente . Spatiul implicit intre componentele
administrate in acest mod este 0 pixeli pe ambele directii .
Trebuie facuta neaparat o observatie legata de acest administrator de dispunere :
componentele vor ocupa totdeauna intregul spatiu al celulei in care trebuie sa se
integreze .
In exemplul de mai jos avem un applet ce creaza un tabel cu 9 celule spatiate la 10
pixeli atat pe verticala cat si pe orizontala :
import java.awt.*;
public class Tabelare extends java.applet.Applet {
GridLayout tabelul=new GridLayout(3,3,10,10);
Button b1=new Button("Steaua");
Button b2=new Button("Dinamo");
Button b3=new Button("Rapid");
Button b4=new Button("National");
Button b5=new Button("Bacau");
Button b6=new Button("Astra");
Button b7=new Button("Otelul");
Button b8=new Button("Sportul");
Button b9=new Button("Petrolul");
public void init() {
setLayout(tabelul);
add(b1);
add(b2);
add(b3);
add(b4);

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 :
-

panoul se umple cu componente inainte de a fi introdus in containerul mai


mare
panoul are propriul administrator de dispunere

Un panou este creat simplu :


Panel panou=new Panel();
Panoului i se atribuie o metoda de dispunere cu ajutorul lui setLayout() . Acesta
functioneaza identic cu setLayout() pentru containere normale . Componentele sunt
adaugate intr-un panou cu metoda add() a acestuia .
ADMINISTRATORUL DE DISPUNERE IN STIVA ( CardLayout )
Dipsunerea in stiva difera de celelalte deoarece ascunde practic unele componente . O
astfel de dispunere inseamna de fapt un grup de containere sau componente afisate
cate unul pe rand - fiecare container din grup fiind numit un card .
In mod normal acest administrator foloseste un panou pentru fiecare card . Mai intai
se introduc componentele in panouri si apoi acestea se introduc in containerul de baza
pentru care s-a stabilit o dispunere in stiva .
Clasa care implementeaza acest administrator este CardLayout .
Dupa ce am stabilit un container cu administrare a dispunerii in stiva trebuie sa
adaugam cardurile sale cu ajutorul unei metode add() de forma :
add(string, container);
Primul argument al metodei este un sir care reprezinta numele cardului . Al doilea
argument specifica containerul sau componenta care reprezinta cardul . Daca este
vorba de un container acesta trebuie sa contina deja toate componentele necesare lui .
Dupa ce am adaugat cardul in containerul principal al programului putem folosi
metoda show() a administratorului de dispunere in stiva pentru a afisa o anumita
cartela . Metoda show() primeste doua argumente :
-

primul este containerul in care au fost adaugate cardurile ; daca respectivul


container este chiar fereastra principala a appletului putem folosi cuvantul
cheie this ca argument
numele cardului

In cele ce urmeaza se va prezenta o modalitate bazata pe fire de executie pentru a


trece de la un card la altul :

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) {}
}
}
}

ADMINISTRATORUL DE DISPUNERE TABELARA NEPROPORTIONALA


(GridBagLayout )
Acesta administrator reprezinta de fapt o extensie a dispunerii tabelare . Exista cateva
diferente intre aceasta dispunere si cea tabelara standard :
-

o componenta poate ocupa mai multe celule ale tabelului


proportiile intre diferitele randuri sau coloane nu trebuie sa fie aceeasi
componentele dispuse in cadrul celulelor pot fi aranjate in diferite moduri

Pentru a crea o astfel de dispunere se folosesc clasa GridBagLayout si clasa


GridBagConstraints . Prima clasa este chiar administratorul de dispunere iar cea de a
doua este folosita pentru a defini constrngerile fiecarei componente ce va fi plasata
intr-o celula - pozitia , dimensiunile , alinierea , etc .
In forma generala crearea unei dispuneri tabelare neproportionale presupune cativa
pasi :
-

crearea unui obiect GridBagLayout si stabilirea sa ca administrator de


dispunere curent
crearea unei noi instante a clasei GridBagConstraints
definirea restrictiilor pentru o componenta
anuntarea componentei si a restrictiilor sale in administratorul de dispunere
introducerea componentei in container

Pentru realizarea in practica a unei astfel de dispuneri sa luam un exemplu direct :


-

prima etapa : proiectarea tabelului

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

etapa a doua : crearea tabelului

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 .
-

etapa a treia : determinarea proportiilor

Acum se vor determina proportiile liniilor si coloanelor in relatiile cu alte linii si


coloane . Cel mai usor este sa luam valorile weightx si weighty ca procente din
latimea si inaltimea totale ale panoului . In acest caz valorile insumate pentru toate
variabilele weightx si weighty trebuie sa fie 100 .
Celulele care ocupa mai multe linii sau coloane trebuie sa aiba totdeauna valoarea o in
directia in care se extind . In afara de acest lucru trebuie sa ne hotaram doar asupra
celulei care va primi o valoare ; toate celelalte de pe rand sau de pe coloana trebuie sa
aiba valoarea 0 .
Scopul acestei etape este de a incerca sa stabilim proportiile de baza ale liniilor si
celulelor care vor apare pe ecran . In general in aceasta etapa vor apare mai multe
incercari pana la obtinerea rezultatului dorit .
-

etapa a patra : adaugarea si aranjarea componentelor

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.BOTH - determina extinderea pentru a umple celula in


ambele directii

GridBagConstraints.NONE - determina afisarea la dimensiunea mimina


necesara componentei
GridBagConstraints.HORIZONTAL - determina extinderea pe orizontala
GridBagConstraints.VERTICAL - determina extinderea pe verticala

Implicit restrictia fill are valoarea NONE pentru toate componentele .


A doua restrictie care afecteaza aparitia unei componente intr-o celula este anchor .
Aceasta se aplica doar componentelor care nu umplu intreaga celula si indica
functiilor AWT unde sa plaseze componenta in cadrul celulei . Valorile posibile pentru
aceasta restrictie sunt :
-

GridBagConstraints.NORTH
GridBagConstraints.NORTHEAST
GridBagConstraints.SOUTH
GridBagConstraints.SOUTHWEST
GridBagConstraints.EAST
GridBagConstraints.SOUTHEAST
GridBagConstraints.WEST
GridBagConstraints.NORTHWEST
GridBagConstraints.CENTER

Valoarea prestabilita pentru ancorare este GridBagConstraints.CENTER .


-

etapa a cincea : ajustari

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() {

GridBagLayout tabelnp=new GridBagLayout();


GridBagConstraints restrictii=new GridBagConstraints();
setLayout(tabelnp);
definireRestrictii(restrictii,0,0,1,1,10,40);
restrictii.fill=GridBagConstraints.NONE;
restrictii.anchor=GridBagConstraints.EAST;
Label eticheta1=new Label("Nume:",Label.LEFT);
tabelnp.setConstraints(eticheta1,restrictii);
add(eticheta1);
definireRestrictii(restrictii,1,0,1,1,90,0);
restrictii.fill=GridBagConstraints.HORIZONTAL;
TextField tfnume=new TextField();
tabelnp.setConstraints(tfnume,restrictii);
add(tfnume);
definireRestrictii(restrictii,0,1,1,1,0,40);
restrictii.fill=GridBagConstraints.NONE;
restrictii.anchor=GridBagConstraints.EAST;
Label eticheta2=new Label("Parola:",Label.LEFT);
tabelnp.setConstraints(eticheta2,restrictii);
add(eticheta2);
definireRestrictii(restrictii,1,1,1,1,0,0);
restrictii.fill=GridBagConstraints.HORIZONTAL;
TextField tfparola=new TextField();
tfparola.setEchoCharacter('*');
tabelnp.setConstraints(tfparola,restrictii);
add(tfparola);
definireRestrictii(restrictii,0,2,2,1,0,20);
restrictii.fill=GridBagConstraints.NONE;
restrictii.anchor=GridBagConstraints.CENTER;
Button butonok=new Button("OK");
tabelnp.setConstraints(butonok,restrictii);
add(butonok);
}
}
In afara restrictiilor discutate anterior mai trebuie amintite inca doua restrictii ipadx si
ipady . Acestea doua controleaza bordurile - spatiul care inconjoara o componenta
dintr-un panou . In mod prestabilit componentele nu au nici un spatiu liber in jurul
lor . Restrictia ipadx adauga un spatiu in stanga si in dreapta componentei iar ipady
adauga deasupra si dedesubtul componentei .
Pentru a determina spatiul lasat in jurul unui panou putem folosi insertiile ( insets ) .
Clasa Insets contine valori pentru insertiile din partea de sus , de jos , din stanga si din
dreapta , valori folosite la desenarea panoului .

Insertiile determina spatiul dintre marginile panoului si comonentele acestuia .


Pentru a modifica insertiile trebuie sa suprascriem metoda insets() - in Java 1.02 , sau
metoda getInsets() din Java2 - ambele metode realizand acelasi lucru .
In cadrul metodei getInsets() ( sau insets() ) se creaza un nou obiect Insets unde
constructorul clasei primeste ca argumente patru valori intregi reprezentand insertiile
pentru partea de sus , din stanga , de jos si din dreapta panoului . Metoda va returna
apoi obiectul Insets . In continuare avem o prezentare a codului necesar pentru
adaugarea insertiilor intr-o dispunere tabelara : 10 pentru partea de sus si de jos si 30
pentru laterale :
public Insets getInsets() {
return new Insets(10,30,10,30);
}
INTERACTIUNEA UTILIZATORULUI CU UN APPLET
Pana acum am vazut cum se poate crea o interfata grafica utilizator - problema este ca
aceasta interfata nu poate face deocamdata nimic ! In cele ce urmeaza vom vedea
modul in care putem determina un applet sa trateze diferite evenimente folosind
tehnici din Java 1.02 - limbajul cel mai raspandit inca pentru crearea appleturilor .
O interfata functionala trebuie sa fie capabila sa raspunda la evenimente - acestea
reprezentand apeluri de metode pe care sistemul de ferestre Java le face ori de cate ori
se interactioneaza cu un element al interfetei grafice create de utilizator .
Un eveniment este generat ca raspuns la aproape orice actiune pe care o poate
intreprinde un utilizator . In programele noastre nu trebuie tratate toate evenimentele ne vom ocupa de fapt doar de cele la care vrem sa reactioneze programul nostru
ignorand restul . Intre evenimentele care pot fi tratate amintim : clicuri demouse ,
miscari ale mouseului , apasari de taste sau evenimente ale interfetei grafice
utilizatoru ( clicuri pe diferite componente , derulari de liste , etc ) .
METODA handleEvent()
Tratarea evenimentelor in Java 1.02 se face prin metoda handleEvent() . Aceasta este
definita in clasa Component care este mostenita de java.applet.Applet - devenind
astfel disponibila appleturilor .
Cand un eveniment este transmis metodei hendleEvent() aceasta apeleaza o metoda
specifica de tratare a evenimentului respectiv . Pentru a trata un anumit eveniment va
trebui sa suprascriem aceste metode specifice . Apoi , la aparitia evenimentului
respectiv metoda noua va fi apelata si executata .
TRATAREA CLICURILOR DE MOUSE
1. Evenimentele mouse down si mouse up

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);
}

public boolean mouseDown(Event evt , int x , int y) {


if (linieCrt<MAXLINII) {
pctInitial=new Point(x,y);
return true;
}
else {
System.out.println("Prea multe linii.");
return false;
}
}
public boolean mouseUp (Event evt , int x , int y) {
if (linieCrt<MAXLINII) {
adaugareLinie(x,y);
return true;
}
else return false;
}
public boolean mouseDrag (Event evt , int x , int y) {
if (linieCrt<MAXLINII) {
pctCurent=new Point(x,y);
repaint();
return true;
}
else return false;
}
void adaugareLinie(int x,int y) {
inceput[linieCrt]=pctInitial;
finalul[linieCrt]=new Point(x,y);
linieCrt++;
pctCurent=null;
pctInitial=null;
repaint();
}
public void paint(Graphics g) {
g.setColor(Color.blue);
for (int i=0;i<linieCrt;i++) {
g.drawLine(inceput[i].x, inceput[i].y, finalul[i].x, finalul[i].y);
}
g.setColor(Color.red);
if (pctCurent!=null)
g.drawLine(pctInitial.x , pctInitial.y , pctCurent.x , pctCurent.y);
}
}

Pentru a ajuta la intelegerea programului vom schita pe scurt si un comentariu al


diferitelor elemente ce apar in cadrul sursei de mai sus .
Programul nostru memoreaz nu valori individuale ale coordonatelor ci obiecte Point .
Tabloul inceput memoreaza punctele care reprezinta punctele de inceput ale liniilor
deja desenate . Tabloul final memoreaza punctele de final ale liniilor deja desenate .
Variabila pctInitial memoreaza punctul de start al liniei pe care o desenam la
momentul curent iar pctCurent retine punctul final al liniei desenate curent . Variabila
linieCrt memoreaza numarul de linii desenate pentru a nu se depasi valoare
MAXLINII si pentru a se cunoaste linia din tablou care se va accesa in continuare .
Evenimentele tratate in applet sunt trei : mouseDown() pentru a stabili punctul de start
al liniei curente , mouseDrag() pentru a desena linia curenta pe masura ce este
desenata si mouseUp() pentru a se stabili punctul final al liniei desenate .
Pe masura ce mouseul este miscat pentru a trasa o noua linie appletul o deseneaza pe
aceasta astfel incat noua linie se va deplasa de la punctul de pornire si pana la punctul
mobil reprezentat de mouse ; evenimentul mouseDrag() memoreaza punctul curent ori
de cate ori mouseul se deplaseaza asa ca aceasta metoda poate fi folosita pentru a
reimprospata afisarea liniei curente dand astfel senzatia de animatie a acestei liniii .
Noua linie desenata se va adauga in tabloul de liniii doar dupa eliberarea mouseului la interventia metodei mouseUp() care apeleaza metoda adaugareLinie() .
Aceasta metoda adaugareLinie() actualizeaza tabloul de linii - de fapt tablourile de
puncte de inceput si de sfarsit ale liniilor dupa care appletul este redesenat pentru a
tine cont de aparitia ultimei linii desenate . Tot in cadrul acestei metode se seteaza
variabilele pctCurent si pctInitial la null deoarece linia desenata curent a fost
finalizata in momentul apelarii acestei metode . Prin setarea aceasta putem apoi testa
aceasta valoare null in metoda paint() pentru a vedea daca trebuie trasata o nou linie .
Desenarea appletului presupune desenarea tuturor liniilor stocate in tablourile
programului precum si desenarea liniei curente ale carei capete sunt in pozitiile
pctInitial si respectiv pctCurent .
Dupa cum am metionat putin mai sus in cadrul metodei paint() intai testam daca
valoarea lui pctCurent este null . Daca da , atunci appletul nu se afla in timpul
desenarii unei linii deci nu va avea nici un motiv sa traseze o linie care nu exista . Prin
testarea variabilei pctCurent - si prin posibilitatea setarii ei la null in metoda
adaugareLinie() - putem desena doar ceea ce este necesar .

S-ar putea să vă placă și