Sunteți pe pagina 1din 25

Programare Java

Curs – 8

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 folosim 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("Astra");
Button b3=new Button("Petrolul");
Button b4=new Button("Vaslui");
Button b5=new Button("CFR");
Button b6=new Button("Pandurii");
Button b7=new Button("U Cluj");
Button b8=new Button("Chiajna");
Button b9=new Button("FC Brasov");

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 directii 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(nord, BorderLayout.PAGE_START);
add(sud, BorderLayout.PAGE_END);
add(est, BorderLayout.LINE_END);
add(vest, BorderLayout.LINE_START);
add(centru, BorderLayout.CENTER); }
}

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)

Dispunerea 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)
Acest 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 constrangerile 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.

Sa presupunem ca schita noastra este urmatoarea:

Nume
Parola

OK

La pasul urmator ar trebui sa tabelam deja interfata noastra etichetand celulele cu


coordonatele lor x, y:

0,0 1,0
Nume
0,1 Parola 1,1

0,2 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: componenta 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 componentele 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 mai nimic ☺. In cele ce urmeaza vom
vedea modul in care putem determina un applet sa trateze diferite evenimente folosind
tehnici Java 1.02.
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 handleEvent() 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 click 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 mentionat 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) {


...
}

Metoda 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 punctul 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 memoreaza 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.

TRATAREA EVENIMENTELOR DE TASTATURA

Un astfel de eveniment apare ori de cate ori este apasata o tasta. Pentru ca un
eveniment de tastatura sa fie receptionat de catre o componenta trebuie ca aceasta sa
fie selectata, sau focalizata - focused. Pentru a indica explicit selectarea unei
componente pentru a primi date de intrare putem apela metoda requestFocus() a
componentei respective, ca in exemplul de mai jos care presupune ca avem un buton
denumit "buton1":

buton1.requestFocus();

Putem selecta chiar intreaga fereastra Applet prin apelarea metodei sale
requestFocus().
EVENIMENTELE keyDown si keyUp

Metodele care asigura tratarea unui eveniment de tastatura sunt de urmatoarea factura:

public boolean keyDown(Event evt, int tasta) {


//...
}

Valorile generate de evenimentele keyDown, care sunt transmise metodei ca


argumentul tasta, sunt intregi care reprezinta valori Unicode; pentru a putea sa le
folosim drept caractere trebuie sa folosim o convertire:

caracter=(char)tasta;

In exemplul de mai jos avem o metoda care afiseaza exact tasta pe care am apasat, ca
si caracter si ca valoare Unicode:

public boolean keyDown(Event evt, int tasta) {


System.out.println("Valoare Unicode: "+tasta);
System.out.println("Caracter: "+(char)tasta);
return true;
}

Metoda inrudita keyUp() are o semnatura identica - exceptand bineinteles numele


metodei.

TASTE PRESTABILITE

Clasa Event are un set de variabile de clasa care reprezinta unele taste nealfanumerice
ca tastele functionale sau cele directionale. Daca interfata appletului nostru foloseste
aceste taste putem testa folosirea lor in cadrul metodei keyDown(). Valorile acestor
variabile de clasa sunt intregi, acest lucru fiind important mai ales pentru folosirea
instructiunii switch in cadrul testarii acestor variabile. Mai jos este prezentat un tabel
care arata variabilele de clasa amintite mai sus:

Event.HOME tasta HOME


Event.END tasta END
Event.PGUP tasta Page Up
Event.PGDN tasta Page Down
Event.UP sageata in sus
Event.DOWN sageata in jos
Event.LEFT sageata la stanga
Event.Right sageata la dreapta
Event.F1 tasta F1
Event.F2 tasta F2
Event.F3 tasta F3
Event.F4 tasta F4
Event.F5 tasta F5
Event.F6 tasta F6
Event.F7 tasta F7
Event.F8 tasta F8
Event.F9 tasta F9
Event.F10 tasta F10
Event.F11 tasta F11
Event.F12 tasta F12

Pentru a exemplifica utilizarea evenimentelor de tastatura vom prezenta un scurt


applet in cadrul carui vom tasta un caracter si apoi il vom misca cu ajutorul tastelor
directionale (sageti); in orice moment putem schimba caracterul prin simpla tastare a
unui alt caracter.
Pentru realizarea acestei operatii folosim de fapt doar trei metode: init(), keyDown() si
paint().
Metoda init() va stabili culoarea de fond, fontul si pozitia initiala a caracterului;
aceasta metoda va contine si un apel requestFocus() - care are ca scop asigurarea
faptului ca respectivele caractere pe care le vom introduce vor fi tratate chiar de
fereastra Applet.
Actuinile propriu-zise ale appletului se desfasoara in cadrul metodei keyDown();
aceasta se bazeaza pe un switch pentru a testa evenimentele de tastatura iar in cazul in
care apare un eveniment al unei taste directionale se vor face modificarile necesare
modificarii pozitiei caracterului din fereastra Applet. Daca evenimentul este provocat
de apasarea unei taste nedirectionale acest lucru va duce la schimbarea caracterului
afisat in fereastra Applet.
Metoda paint() afiseaza doar caracterul curent la pozitia curenta. Unicul lucru de
mentionat este faptul ca la lansarea appletului nu se deseneaza nimic - inca nu s-a
tastat nici un caracter; variabila tastaCrt va fi initializata cu 0 iar desenarea se va face
doar dupa testarea acestei variabile:

import java.awt.*;
public class Taste extends java.applet.Applet {
char tastaCrt;
int xCrt;
int yCrt;

public void init() {


xCrt=(size().width/2)-8;
yCrt=(size().height/2)-16;
setBackground(Color.red);
setFont(new Font("Helvetica",Font.BOLD,36));
requestFocus();
}
public boolean keyDown(Event evt, int tasta) {
switch (tasta) {
case Event.DOWN:
yCrt+=5;
break;
case Event.UP:
yCrt-=5;
break;
case Event.LEFT:
xCrt-=5;
break;
case Event.RIGHT:
xCrt+=5;
break;
default:
tastaCrt=(char)tasta;
}
repaint();
return true;
}
public void paint(Graphics g) {
if (tastaCrt!=0) {
g.drawString(String.valueOf(tastaCrt),xCrt,yCrt);
}
}
}

TESTAREA TASTELOR SHIFT, CONTROL SI ALT

Aceste taste nu genereaza evenimente proprii insa atunci cand tratam un eveniment
obisnuit - de tastatura sau mouse - putem testa daca vreuna dintre aceste trei taste a
fost apasata pe durata evenimentului.
Clasa Event ofera trei metode pentru a testa apasarea uneia dintre tastele amintite mai
sus: shiftDown(), metaDown() si controlDown(). Toate aceste metode returneaza
valori booleene in functie de starea de apasare a tastelor respective.
Tasta Meta este echivalentul tastei ALT pe PC si al tastei Command pe MacIntosh.
Putem apela la aceste metode in oricare dintre metodele de tratare a evenimentelor
prin apelarea lor pentru obiectul eveniment transmis metodei:

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


if (evt.shiftDown())
// trateaza evenimentul shift+clic
else if (evt.controlDown())
// trateaza evenimetul CTRL+clic
else // trateaza evenimentul clic
}

Aceste metode mai pot fi folosite si pentru a testa care dintre butoanele mouseului au
generat un anumit eveniment de mouse in cazul sistemelor cu doua sau trei butoane
ale mouseului. In mod prestabilit evenimentele de mouse sunt generate indiferent de
butonul apasat. Totusi Java asociaza apasarile pe butonul din drepta sau din mijloc cu
apasarile tastelor de modificare Meta si Control asa ca prin testarea acestor taste se
poate afla butonul de mouse care a fost apasat. Prin testarea tastelor de modificare
putem afla care buton de mouse a fost folosit executand alte actiuni diferite decat cele
pe care le-am fi folosit in mod normal pentru butonul din stanga. Se poate folosi
instructiunea if pentru a testa fiecare caz, ca in exemplul de mai jos:

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


if (evt.metaDown())
// trateaza evenimentul clic pe butonul din dreapta al mouseului
else if (evt.controlDown())
// trateaza evenimentul clic pe butonul din mijloc al mouseului
else // trateaza evenimentul clic normal
}

TRATAREA EVENIMENTELOR PRIN METODA GENERICA

Metodele prestabilite prezentate mai sus sunt apelate de o metoda generica de tratare a
evenimentelor - handleEvent(). La folosirea ei, AWT trateaza in mod generic
evenimentele care apar intre componentele aplicatiei sau evenimentele datorate
actiunilor utilizatorului.
In metoda handleEvent() se proceseaza evenimentele de baza si se apeleaza metodele
despre care am vorbit mai devreme. Pentru a trata si alte evenimente decat cele
mentionate deja, pentru a modifica comportamentul implicit de tratare a
evenimentelor sau pentru a crea si a transmite propriile evenimente va trebui sa
suprascriem metoda handleEvent(). Ea are o semnatura de forma:

public boolean handleEvent(Event evt) {


/...
}

Pentru a testa anumite evenimente trebuie sa examinam variabila de instanta id a


obiectului Event. Identificatorul de eveniment este un intreg dar clasa in clasa Event
este definit un ansamblu de evenimente drept variabile de clasa, ale caror nume pot fi
testate in metoda handleEvent(). Deoarece aceste variabile de clasa sunt constante
intregi poate fi folosita cu succes instructiunea handleEvent(). Mai jos avem un
exemplu de metoda handleEvent() in care sunt afisate informatii de depanare despre
evenimentele de mouse:

public boolean handleEvent(Event evt) {


switch (evt.id) {
case Event.MOUSE_DOWN: System.out.println("MouseDown "+evt.x+","+evt.y);
return true;
case Event.MOUSE_UP: System.out.println("MouseUp "+evt.x+","+evt.y);
return true;
case Event.MOUSE_MOVE: System.out.println("MouseMove "+evt.x+","+evt.y);
return true;
case Event.MOUSE_Drag: System.out.println("MouseDrag "+evt.x+","+evt.y);
return true;
default: return false;
}
}
Putem testa si urmatoarele evenimente de tastatura:

- Event.KEY_PRESS - generat cand este apasata o tasta (analog cu metoda


keyDown())
- Event.KEY_RELEASE - generat la eliberarea unei taste
- Event.KEY_ACTION si Event.KEY_ACTION_RELEASE - generate cand
este apasata si respectiv eliberata o tasta functionala (tastele F, directionale,
Page Up, Page Down, Home, etc.)

In ceea ce priveste evenimentele de mouse putem testa si in cazul lor mai multe
evenimente:

- Event.MOUSE_DOWN - generat la apasarea butonului mouseului (analog cu


metoda mouseDown())
- Event.MOUSE_UP - generat cand butonul mouseului este eliberat (analog cu
metoda mouseUp())
- Event.MOUSE_MOVE - generat cand mouseul este deplasat (analog cu
metoda mouseMove())
- Event.MOUSE_DRAG - generat cand mouseul este deplasat tinandu-se apasat
butonul acestuia (analog cu metoda mouseDrag())
- Event.MOUSE_ENTER - generat la intrarea cursorului mouseului pe
suprafata appletului sau a unei componente a acestuia (analog cu metoda
mouseEnter())
- Event.MOUSE_EXIT - generat cand cursorul mouseului paraseste appletul
(analog cu metoda mouseExit())

Mentionam ca la suprascrierea metodei handleEvent() in clasa noastra nici una dintre


metodele prestabilite de tratare a evenimentelor nu va mai fi apelata decat daca o vom
apela explicit in corpul metodei handleEvent(). Cea mai buna modalitate de a rezolva
aceasta problema este de a testa evenimentele de care suntem interesati iar daca
acestea nu apara sa apelam metoda super.handleEvent() - pentru ca superclasa care
defineste metoda sa poata procesa evenimentele. Pentru a exemplifica acest lucru
prezentam listingul de mai jos:

public boolean handleEvent(Event evt) {


if (evt.id==Event.MOUSE_DOWN) {
// proceseaza evenimentul mouse down
return true;
} else
return super.handleEvent(evt);
}

Mai trebuie retinut ca metoda handleEvent() returneaza si ea o valoare booleana.


Valoarea returnata va fi false daca transferam evenimentul unei alte metode (care si ea
la randul ei va returna un true sau false) sau true daca tratam evenimentul in corpul
metodei noastre. Daca transferam tratarea evenimentului unei superclase metoda
respectiva va returna true sau false astfel ca nu trebuie sa mai returnam explicit o
valoare.
TRATAREA EVENIMENTELOR COMPONENTELOR

Aceste evenimente au loc pe componente de genul butoane, zone de text sau alte
elemente ale interfetelor grafice utilizator. Spre exemplu butoanele folosesc
evenimente declansate la apasarea lor; nu mai conteaza evenimentele mouse down sau
mouse up sau locul unde a aparut un clic - componenta se va ocupa de tratarea tuturor
acestor evenimente.
Exista trei tipuri de evenimente ce pot fi generate prin interactiunea cu componentele
interfetei:

- evenimente de actiune (action events) - sunt principalele evenimente din


aceasta categorie, ele indica faptul ca respctivele componente au fost activate.
Evenimentele de actiune sunt generate cand se apasa un buton, se selecteaza o
optiune sau se apasa tasta ENTER intr-un camp de text
- evenimente de selectare/deselectare (list select/deselect events) - acestea sunt
generate atunci cand se selecteaza o caseta de validare sau o optiune dintr-un
meniu; aceste evenimente declanseaza de asemenea si un eveniment de actiune
- evenimente de primire/cedare a selectiei (got/lost focus events) - sunt generate
de orice componenta, ca raspuns la un clic de mouse sau la selectionarea prin
tasta TAB. Primirea selectiei (got focus) inseamna ca respectiva componenta
este selectionata si poate fi activata sau poate primi date de intrare. Cedarea
selectiei (lost focus) inseamna ca s-a selectat o alta componenta.

TRATAREA EVENIMENTELOR DE ACTIUNE

Pentru a intercepta un astfel de eveniment se defineste in applet o metoda action(), cu


semnatura:

public boolean action(Event evt, Object arg) {


//...
}

Aceasta metoda action(), ca si metodele de tratare a evenimentelor de mouse sau


tastatura, primeste ca argument un obiect ce se refera la evenimentul respectiv; ea
primeste si un al doilea argument, un obiect ce poate fi de orice tip. Tipul acestui al
doilea argument e dat de componenta interfetei care a generat actiunea. Mai jos avem
prezentate argumentele suplimentare pentru fiecare tip de componenta:

Componenta Tipul argumentului semnificatia


butoane String eticheta butonului
casete de validare Boolean totdeauna true
butoane radio Boolean totdeauna true
meniuri de optiuni String eticheta elementului
selectat
campuri de text String textul din cadrul campului

In metoda action() primul lucru facut este testarea componentei care a generat
actiunea. Obiectul Event pe care il primim ca argument in apelul action() contine o
variabila de instanta numita target, care contine o referinta catre obiectul ce a generat
evenimentul. Putem folosi operatorul instanceof pentru a afla ce componenta a
generat evenimentul, ca in exemplul de mai jos:

public boolean action(Event evt, Object arg) {


if (evt.target instanceof textField)
return trateazaText(evt.target);
else if (evt.target instanceof Choice);
return trateazaChoice(arg);
//...
return false;
}

In exemplul anterior metoda action putea fi generata de o componenta TextField sau


de un meniu de optiuni.
Metoda action() returneaza o valoare booleana, true daca va trata evenimentul si false
in caz contrar.
In cazul in care avem mai multe componente din aceeasi clasa - de exemplu butoane -
pot apare unele probleme. Toate pot genera actiuni si toate sunt instante ale aceleiasi
clase Button. Aici apare utilizarea argumentului suplimentar: folosind comparatii
simple de siruri, putem folosi etichete, elemente sau continutul componentei pentru a
determina care dintre ele a generat evenimentul.
Un exemplu de astfel de solutie apare in continuare:

public boolean action(Event evt, Object obj) {


if (evt.target instanceof Button) {
String eticheta=(String)arg;
if (eticheta.equals("OK"))
// trateaza butonul OK
else if (eticheta.equals("EXIT"))
// trateaza butonul EXIT
else if (eticheta.equals("STOP"))
// trateaza butonul STOP
...
}
}

In cazul casetelor de validare sau al butoanelor radio argumentul suplimentar este


totdeauna true si nu ne ajuta la diferentiere componentelor. In general nu se prea
reactioneaza direct la activarea unei casete de validare sau la apasarea unui buton
radio, acestea fiind de obicei selectate si abia apoi valorile lor sunt testate in alt loc, de
obicei dupa apasarea unui buton. Daca vrem totusi ca programul sa reactioneze direct
la evenimentele amintite putem folosi in locul argumentului suplimentar metoda
getLabel() pentru a extrage eticheta casetei de validare si a diferentia astfel intre ele
componentele de acest tip.

TRATAREA EVENIMENTELOR DE SELECTARE


Intre aceste evenimente avem: list select, list deselect, got focus si lost focus. Pentru
ultimele doua evenimente putem folosi metodele gotFocus() si lostFocus() - care se
folosesc la fel ca metoda action(), cu urmatoarele semnaturi:

public bolean gotFocus(Event evt, Object arg) {


//...
}
public boolean lostFocus(Event evt, Object arg) {
//...
}

Pentru tratarea primelor doua evenimente trebuie folosita metoda handleEvent(), ca in


exemplul de mai jos:

public boolean handleEvent(Event evt) {


if (evt.id==Event.LIST_SELECT)
handleSelect(Event);
else if (evt.id==Event.LIST_DESELECT)
handleDeselect(Event);
else return super.handleEvent(evt);
}

Event.LIST_SELECT si Event.LIST_DESELECT reprezinta identificatorii


evenimentelor de selectare/deselectare iar controlul lor este transferat catre doua
metode ajutatoare - handleSelect() si handleDeselect(). Apelul super.handleEvent()
permite celorlalte evenimente sa fie transferate fara probleme catre metoda
handleEvent() originala.

EVENIMENTELE ZONELOR DE TEXT

Zonele de text au aceleasi evenimente ca si campurile de text. Putem folosi metodele


gotFocus() si lostFocus() pentru a intercepta evenimentele de primire/cedare a
selectiei la fel ca in exemplele de mai sus ale acelorasi metode.

EVENIMENTE ALE LISTELOR DERULANTE

Aceste liste genereaza trei tipuri de evenimente; selectarea sau deselectarea unui
element din lista are ca efect un eveniment de selectare/deselectare din lista iar dublul
clic executat pe un element al listei are ca efect un eveniment de actiune.
Putem suprascrie metoda action() pentru a trata elementul din lista pe care s-a efectuat
dublu clic. Pentru selectiile si deselectiile din lista putem suprascrie metoda
handleEvent() si apoi sa testam identificatorii de evenimente LIST_SELECT si
LIST_DESELECT.

EVENIMENTE ALE BARELOR DE SCROLL


Pentru a trata evenimentele acestea trebuie folosita metoda handleEvent(). In
continuare avem identificatorii de evenimente relevanti si miscarile care declanseaza
aceste evenimente.

Identificatorul evenimentului Semnificatia


SCROLL_ABSOLUTE generat la deplasarea casetei barei de
scroll
SCROLL_LINE_DOWN generat la selectarea butonului din capatul
de jos sau din stanga al barei de csroll
SCROLL_LINE_UP generat la selectarea butonului din capatul
de sus sau din dreapta al barei de csroll
SCROLL_PAGE_DOWN generat la selectarea spatiului de sub sau
din stanga casetei barei de scroll
SCROLL_PAGE_UP generat la selectarea spatiului de deasupra
sau din dreapta casetei barei de scroll

Toate detaliile teoretice de pana acum s-ar putea sa para greu de inteles fara o
exemplificare practica. Tocmai pentru a arata utilizarea diferitelor evenimente si
tratarea lor vom prezenta un applet care va avea cinci butoane cu denumirea a cinci
culori; la executarea unui clic pe oricare buton fondul appletului se va modifica la
culoarea inscrisa pe buton si va apare un text care ne va anunta culoarea pe care am
selectat-o.
Intr-o prima etapa a construirii appletului nostru vom crea componentele si se va
stabili modul lor de dispunere in fereastra. In exemplul nostru vom folosi un
administrator de dispunere de tip FlowLayout pe care il vom aplica apoi containerului
nostru.
Odata cu apasarea butoanelor noastre se vor genera evenimente de actiune. Pentru
tratarea lor vom folosi metoda action() care in practica va realiza mai multe lucruri:

- testeaza daca initiatorul evenimentului este un buton


- afla care este butonul initiator
- schimba culoarea fondului
- apeleaza metoda paint() pentru aplicare in fapt a culorii noii pe ecran

Pentru a modulariza cat mai corect codul sursa vom crea o metoda action() care va
apela in fapt o alta metoda schimbaCuloare(); aceasta metoda primeste ca argument
chiar obiectul buton care a initiat evenimentul.
Folosind faptul ca argumentul suplimentar al metodei action() este eticheta (in cazul
butoanelor) putem afla care dintre butoane a fost apasat. In cazul de fata nu vom mai
folosi solutia comparatiei etichetei butonului cu un anumit text. Obiectul transmis ca
argument metodei schimbaCuloare() este o instanta a clasei Button iar una dintre
variabilele de instanta este o referinta la acelasi obiect. In metoda noastra vom
compara cele doua variabile pentru a testa daca este vorba de acelasi obiect, dupa care
vom stabili culoarea de fond si apelam metoda repaint().
In continuare avem si listingul complet al aplicatiei comentate in randurile anterioare:

import java.awt.*;

public class CuloareFundal extends java.applet.Applet {


String sir="Apasa un buton pentru a schimba culoarea de fond";
Button butonRosu,butonAlbastru,butonVerde,butonAlb,butonNegru;
public void init() {
setBackground(Color.white);
setLayout(new FlowLayout(FlowLayout.CENTER,10,10));

butonRosu=new Button("Rosu");
add(butonRosu);
butonAlbastru=new Button("Albastru");
add(butonAlbastru);
butonVerde=new Button("Verde");
add(butonVerde);
butonAlb=new Button("Alb");
add(butonAlb);
butonNegru=new Button("Negru");
add(butonNegru);
}

public boolean action(Event evt, Object arg) {


if (evt.target instanceof Button) {
schimbaCuloare((Button)evt.target);
return true;
} else return false;
}

void schimbaCuloare(Button b) {
if (b==butonRosu) { setForeground(Color.white);sir="Fond
rosu";setBackground(Color.red);}
else if (b==butonAlbastru) { setForeground(Color.white);sir="Fond
albastru";setBackground(Color.blue);}
else if (b==butonVerde) { setForeground(Color.red);sir="Fond
verde";setBackground(Color.green);}
else if (b==butonAlb) { setForeground(Color.red);sir="Fond
alb";setBackground(Color.white);}
else { setForeground(Color.white);sir="Fond
negru";setBackground(Color.black);}

repaint();
}

public void paint(Graphics ecran) {


ecran.drawString(sir,100,50);
}
}

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