Sunteți pe pagina 1din 24

Universitatea Lucian Blaga din Sibiu

Facultatea de tiine
Departamentul de Matematic i Informatic

Disciplina: Metode avansate de programare


Cadru didactic: Ralf Fabian
Specializarea: Informatic, anul II.

Interfaa grafic n Java


Interfaa grafic cu utilizatorul (GUI), este un termen cu neles larg care se refer la toate
tipurile de comunicare vizual ntre un program i utilizatorii si. De la apariia limbajului Java,
bibliotecile de clase care ofer servicii grafice au suferit probabil cele mai mari schimbri n
trecerea de la o versiune la alta. Acest lucru se datoreaz, pe de o parte dificultii legate de
implementarea noiunii de portabilitate, pe de alt parte nevoii de a integra mecanismele GUI cu
tehnologii aprute i dezvoltate ulterior, cum ar fi Java Beans. In momentul actual, exist dou
modaliti de a crea o aplicaie cu interfa grafic i anume:
AWT (Abstract Windowing Toolkit) - este API-ul iniial pus la dispoziie ncepnd cu
primele versiuni de Java;
Swing - parte dintr-un proiect mai amplu numit JFC (Java Foundation Classes) creat n urma
colaborrii dintre Sun, Netscape i IBM, Swing se bazeaz pe modelul AWT, extinznd
funcionalitatea acestuia i adugnd sau nlocuind componente pentru dezvoltarea
aplicaiilor GUI.
Este de preferat ca aplicaiile Java s fie create folosind tehnologia Swing, aceasta punnd la
dispoziie o palet mult mai larg de faciliti, ns nu se renun complet la AWT deoarece aici
exist clase eseniale, reutilizate n Swing.
In principiu, crearea unei aplicaii grafice presupune urmtoarele lucruri:
1. Design
Crearea unei suprafee de afiare (cum ar fi o fereastr) pe care vor fi aezate
obiectele grafice (componente) care servesc la comunicarea cu utilizatorul (butoane,
controale pentru editarea textelor, liste, etc);
Crearea i aezarea componentelor pe suprafaa de afiare la poziiile
corespunztoare;
2. Funcionalitate
Definirea unor aciuni care trebuie s se execute n momentul cnd utilizatorul
interacioneaz cu obiectele grafice ale aplicaiei;
Ascultarea evenimentelor generate de obiecte n momentul interaciunii cu
utilizatorul i executarea aciunilor corespunztoare, aa cum au fost ele definite.

Ierarhia de componente AWT

Componente AWT

Ierarhia de componete Swing

Componente Swing

Interfaa grafic cu pachetul AWT


Pachetul care ofer componente AWT este java.awt. Obiectele grafice sunt derivate din
Component, cu excepia meniurilor care descind din clasa MenuComponent.
Prin noiunea de component se nelege orice obiect care poate avea o reprezentare grafic
i care poate interaciona cu utilizatorul. Exemple de componente sunt ferestrele, butoanele, listele,
bare de defilare, etc. Toate componentele AWT sunt definite de clase proprii ce se gsesc n
pachetul java.awt, clasa Component fiind superclasa abstract a tuturor acestor clase.
Crearea obiectelor grafice nu realizeaz automat i afiarea lor pe ecran. Mai nti ele
trebuie aezate pe o suprafa de afiare, care poate fi o fereastr, i vor deveni vizibile n momentul
n care suprafaa pe care sunt afiate va fi vizibil. O astfel de suprafa pe care sunt plasate
componente se mai numete container i reprezint o instan a unei clase derivate din Container.
Clasa Container este o subclas aparte a lui Component, fiind la rndul ei superclasa tuturor
suprafeelor de afiare Java.
n momentul n care utilizatorul a efectuat o aciune, componentele trebuie s genereze
evenimente n funcie de aciunea pe care au suferit-o (aciune transmis de la tastatur, mouse,
etc.). ncepnd cu versiunea 1.1 a limbajului Java, evenimentele sunt instane ale claselor derivate
din AWTEvent.
Un eveniment este produs de o aciune a utilizatorului asupra unui obiect grafic, deci
evenimentele nu trebuie generate de programator. n schimb, ntr-un program trebuie specificat
codul care se execut la apariia unui eveniment. Tratarea evenimentelor se realizeaz prin
intermediul unor clase de tip listener (asculttor, consumator de evenimente), clase care sunt
definite n pachetul java.awt.event.
Exemplu 1. O fereastr cu dou butoane.
//varianta AWT
import java.awt.*;
public class FirstGUI{
public static void main ( String args []) {
// Crearea ferestrei - un obiect de tip Frame
Frame f = new Frame ("Prima mea fereastra");
// Setarea modului de dipunere a componentelor
f.setLayout (new FlowLayout());
// Crearea celor doua butoane
Button b1 = new Button ("OK");
Button b2 = new Button ("Cancel");
// Adaugarea butoanelor
f.add(b1);
f.add(b2);
f.pack();
// Afisarea fereastrei
f.setVisible(true);
}
}
//varianta Swing
import java.awt.*;
import javax.swing.*;
public class FirstGUISwing {
public static void main(String args[]) {
// Crearea ferestrei - un obiect de tip Frame
JFrame f = new JFrame("Prima mea fereastra");
// setarea actiune implicite de terminare a
// aplicatiei la inchiderea ferestrei
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

// Setarea modului de dipunere a componentelor


f.setLayout(new FlowLayout());
// Crearea celor doua butoane
JButton b1 = new JButton("OK");
JButton b2 = new JButton("Cancel");
// Adaugarea butoanelor
f.add(b1);
f.add(b2);
f.pack();
// Afisarea fereastrei
f.setVisible(true);
}
}

Att butoanele adugate ct i butonul de nchidere a ferestrei pot fi apsate, dar nu


realizeaz nimic. Acest lucru se ntmpl deoarece nu s-a specificat nicieri codul care trebuie s se
execute la apsarea acestor butoane. De asemenea, mai trebuie remarcat c nu s-a specificat nicieri
dimensiunile ferestrei sau ale butoanelor i nici poziiile de amplasare. Cu toate acestea ele sunt
plasate unul lng celalalt, fr s se suprapun iar suprafaa ferestrei este suficient de mare nct s
cuprind ambele obiecte. Aceste fenomene sunt provocate de un obiect special de tip
FlowLayout care se ocup cu gestionarea ferestrei i cu plasarea componentelor ntr-o anumit
ordine pe suprafaa ei. Aadar, modul de aranjare nu este o caracteristic a suprafeei de afiare ci,
fiecare container are asociat un obiect care se ocup cu dimensionarea i dispunerea componentelor
pe suprafaa de afiare i care se numete gestionar de poziionare (layout manager).

Generaliti despre componentele AWT


n pachetul java.awt, se regsesc urmtoarele clasa de componente:
Button - butoane cu eticheta format dintr-un text pe o singur linie;
Canvas - suprafa pentru desenare;
Checkbox - component ce poate avea dou stri; mai multe obiecte de acest tip pot fi
grupate folosind clasa CheckBoxGroup;
Choice - liste n care doar elementul selectat este vizibil i care se deschid la apsarea lor;
Container - superclasa tuturor suprafeelor de afiare;
Label - etichete simple ce pot conine o singur linie de text needitabil;
List - liste cu selecie simpl sau multipl;
Scrollbar - bare de defilare orizontale sau verticale;
TextComponent - superclasa componentelor pentru editarea textului: TextField (pe o
singur linie) i TextArea (pe mai multe linii).
Din cauza unor diferene eseniale n implementarea meniurilor pe diferite platforme de
operare, acestea nu au putut fi integrate ca obiecte de tip Component, superclasa care
descrie meniuri fiind MenuComponent.

Componentele AWT au peste 100 de metode comune, motenite din clasa Component. Acestea
servesc uzual pentru aflarea sau setarea atributelor obiectelor, cum ar fi: dimensiune, poziie,
culoare, font, etc. i au formatul general getProprietate, respectiv setProprietate. Cele mai folosite,
grupate pe tipul proprietii gestionate sunt:
Poziie
getLocation, getX, getY, getLocationOnScreen,
setLocation, setX, setY

Dimensiuni
getSize, getHeight, getWidth
setSize, setHeight, setWidth

Dimensiuni i poziie
getBounds
setBounds

Culoare
getForeground, getBackground
setForeground, setBackground

Font
getFont
setFont

Vizibilitate
setVisible
isVisible

Interactivitate
setEnabled
isEnabled

Generaliti despre suprafee de afiare


Mai nti obiectele grafice trebuie aezate pe o suprafa, i vor deveni vizibile n momentul
n care suprafaa respectiv va fi vizibil. O astfel de suprafa pe care sunt plasate componentele se
numete suprafaa de afiare sau container i reprezint o instan a unei clase derivat din
Container.
O parte din clasele care au drept printe pe Container sunt urmtoarele:
Window - este superclasa tuturor ferestrelor. Din aceast clas sunt derivate:
Frame - ferestre standard;
Dialog - ferestre de dialog modale sau nemodale;
Panel - o suprafa fr reprezentare grafic folosit pentru gruparea altor componente. Din
aceast clas deriv Applet, folosit pentru crearea appleturilor.
6

ScrollPane - container folosit pentru implementarea automat a derulrii pe orizontal sau

vertical a unei componente.

Componentele adugate sunt memorate ntr-o list iar poziiile lor din aceast list vor defini
ordinea de traversare front-to-back a acestora n cadrul containerului. Dac nu este specificat nici
un index la adugarea unei componente, atunci ea va fi adugat pe ultima poziie a listei.
Clasa Container conine metodele comune tuturor suprafeelor de afiare. Cele mai
folosite sunt:
add - permite adugarea unei componente pe suprafaa de afiare. O component nu poate
aparine dect unui singur container, ceea ce nseamn c pentru a muta un obiect dintr-un
container n altul trebuie eliminat mai nti de pe containerul iniial.
remove - elimin o component de pe container;
setLayout - stabilete gestionarul de poziionare al containerului;
getInsets - determin distana rezervat pentru marginile suprafeei de afiare;
validate - foreaz containerul s reaeze toate componentele sale. Aceast metod
trebuie apelat explicit atunci cnd se adaug sau se elimin componente pe suprafa de
afiare dup ce aceasta a devenit vizibil.
Frame f = new Frame("O fereastra");
// Adauga un buton direct pe fereastra
Button b = new Button("Hello");
f.add(b);
// Adauga doua componente pe un panel
Label et = new Label("Nume:");
TextField text = new TextField();
Panel panel = new Panel();
panel.add(et);
panel.add(text);
// Adauga panel-ul pe fereastra i, indirect, cele doua componente
f.add(panel);

Gestionarea poziionrii
Un gestionar de poziionare (layout manager) este un obiect care controleaz dimensiunea
i aranjarea (poziia) componentelor unui container. Aadar, modul de aranjare a componentelor pe
o suprafaa de afiare nu este o caracteristica a clasei Container. Fiecare obiect de tip
Container, sau o extensie a lui (Applet, Frame, Panel) are asociat un obiect care se ocupa
cu dispunerea componentelor pe suprafaa sa: gestionarul de poziionare. Toate clasele care
instaniaz obiecte pentru gestionarea poziionrii implementeaz interfaa LayoutManager. La
7

instanierea unui container se creeaz implicit un gestionar de poziionare asociat acestui container.
De exemplu pentru o fereastra (un obiect de tip Window sau o subclasa a sa) gestionarul implicit
este de tip BorderLayout, n timp ce pentru un container de tip Panel este o instan a clasei
FlowLayout.

Folosirea gestionarilor de poziionare


Orice container are un gestionar implicit de poziionare - un obiect care implementeaz
interfaa LayoutManager, acesta fiindu-i ataat automat la crearea sa. n cazul n care acesta nu
corespunde necesitilor noastre el poate fi schimbat cu uurin. Cei mai utilizai gestionari din
pachetul java.awt sunt:

FlowLayout
BorderLayout
GridLayout
CardLayout

Ataarea explicit a unui gestionar de poziionare la un container se face cu metoda setLayout a


clasei Container. Metoda poate primi ca parametru orice instan a unei clase care implementeaz
interfaa LayoutManager. Secvena de ataare a unui gestionar pentru un container este:
FlowLayout gestionar = new FlowLayout();
container.setLayout(gestionar);

sau, mai uzual :


container.setLayout(new FlowLayout());

Programele nu apeleaz n general metode ale gestionarilor de poziionare iar n cazul cnd
avem nevoie de obiectul gestionar l putem obine cu metoda getLayout din clasa Container.
Una din facilitile cele mai utile oferite de gestionarii de poziionare este rearanjarea
componentele unui container atunci cnd acesta este redimensionat. Poziiile i dimensiunile
componentelor nu sunt fixe, ele fiind ajustate automat de ctre gestionar la fiecare redimensionare
astfel nct sa ocupe ct mai estetic suprafaa de afiare.
Pentru situaii n care se dorete o amplasare a componentelor la anumite poziii fixe, iar
acestea s rmn acolo chiar dac se redimensioneaz containerul, se trimite argumentului null
metodei setLayout:
//pozitionare absoluta a componentelor in container
container.setLayout(null);

Folosind poziionarea absoluta, nu va mai fi suficient adugarea cu metoda add a


componentelor n container ci va trebui specificat poziia i dimensiunea lor - acest lucru era fcut
automat de gestionarul de poziionare.
container.setLayout( null );
Button b = new Button("Buton");
b.setSize(10, 10);
b.setLocation (0, 0);
b.add();

In general, se recomanda folosirea gestionarilor de poziionare n toate situaiile cnd acest


lucru este posibil, deoarece permit programului sa aib aceeai nfiare indiferent de platforma
i rezoluia pe care este rulat.
8

Gestionarul FlowLayout
Acest gestionar aeaz componentele pe suprafaa de afiare n flux liniar, mai precis,
componentele sunt adugate una dup alta pe linii, n limita spaiului disponibil. In momentul cnd
o componenta nu mai ncape pe linia curenta se trece la urmtoarea linie, de sus n jos.
Adugarea componentelor se face de la stnga la dreapta pe linie, iar alinierea obiectelor n cadrul
unei linii poate fi de trei feluri: la stnga, la dreapta, centrate. Implicit componentele sunt centrate
pe fiecare linie iar distanta implicita ntre componente este de 5 uniti pe verticala i 5 pe
orizontal.
Exemplu 2.
import java.awt.*;
import javax.swing.*;
public class TestFlowLayout {
public static void main(String args[]) {
JFrame f = new JFrame("Flow Layout");
f.setLayout(new FlowLayout());
JButton
JButton
JButton
JButton
JButton

b1
b2
b3
b4
b5

f.add(b1);

=
=
=
=
=

new
new
new
new
new

JButton("Button 1");
JButton("2");
JButton("Button 3");
JButton("Long-Named Button 4");
JButton("Button 5");

f.add(b2); f.add(b3); f.add(b4); f.add(b5);

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

Componentele ferestrei vor fi afiate astfel:

Redimensionnd fereastra astfel nct cele cinci butoane sa nu mai ncap pe o linie, ultimele dintre
ele vor fi trecute pe linia urmtoare:

Gestionarul BorderLayout
Gestionarul BorderLayout mparte suprafaa de afiare n cinci regiuni, corespunztoare
celor patru puncte cardinale i centrului. O componenta poate fi plasata n oricare din aceste regiuni,
9

dimensiunea componentei fiind calculata astfel nct sa ocupe ntreg spaiul de afiare oferit de
regiunea respectiva. Pentru a aduga mai multe obiecte grafice ntr-una din cele cinci zone, ele
trebuie grupate n prealabil ntr-un panel, care va fi amplasat apoi n regiunea dorita.
Aadar, la adugarea unei componente pe o suprafa gestionat de BorderLayout, metoda add
va mai primi pe lng numele componentei i zona n care aceasta va fi amplasata, acesta fiind
specificat prin una din constantele clasei BorderLayout: NORTH, SOUTH, EAST, WEST,
CENTER.
Exemplu 3.
import java.awt.BorderLayout;
import javax.swing.*;
import static java.awt.BorderLayout.*;
public class TestBorderLayout {
public static void main(String args[]) {
JFrame f = new JFrame("Border Layout");
// poate sa lipseasca, e implicit la JFrame
f.setLayout(new BorderLayout());
f.add(new JButton("Nord"), NORTH);
f.add(new JButton("Sud"), SOUTH);
f.add(new JButton("Est"), EAST);
f.add(new JButton("Vest"), WEST);
f.add(new JButton("Centru"), CENTER);
f.pack();
f.setVisible(true);
}
}

Cele cinci butoane ale ferestrei vor fi afiate astfel:

La redimensionarea ferestrei se pot observa urmtoarele lucruri: nordul i sudul se redimensioneaz


doar pe orizontala, estul i vestul doar pe verticala, n timp ce centrul se redimensioneaz att pe
orizontala ct i pe verticala. Redimensionarea componentelor se face astfel nct ele ocupa toat
zona containerului din care fac parte.

Gestionarul GridLayout
Gestionarul GridLayout organizeaz containerul ca un tabel cu rnduri i coloane,
componentele fiind plasate n csuele tabelului de la stnga la dreapta ncepnd cu primul rnd.
Csuele tabelului au dimensiuni egale iar o component poate ocupa doar o singura csu.
Numrul de linii i coloane poate fi specificat n constructorul gestionarului dar poate fi modificat i
ulterior prin metodele setRows i setCols. De asemenea, distanta ntre componente pe orizontala
i distanta ntre rndurile tabelului pot fi specificate n constructor sau stabilite ulterior.
Exemplu 4.
10

import java.awt.*;
import javax.swing.*;
public class TestGridLayout {
public static void main(String args[]) {
JFrame f = new JFrame("Grid Layout");
f.setLayout(new GridLayout(3, 2));
f.add(new JButton("Button 1"));
f.add(new JButton("2"));
f.add(new JButton("Button 3"));
f.add(new JButton("Long-Named Button 4"));
f.add(new JButton("Button 5"));
f.pack();
f.setVisible(true);
}
}

Cele cinci butoane ale ferestrei vor fi pe trei rnduri i doua coloane astfel:

Redimensionarea ferestrei va determina redimensionarea tuturor componentelor.

Gestionarul CardLayout
Gestionarul CardLayout trateaz componentele adugate pe suprafaa sa ntr-o manier
similar cu cea a dispunerii crilor de joc ntr-un pachet. Suprafaa de afiare poate fi asemnat cu
pachetul de cri iar fiecare component este o carte din pachet. La un moment dat, numai o singur
component este vizibil.
Clasa dispune de metode prin care s poat fi afiat o anumit component din pachet, sau
s se poat parcurge secvenial pachetul, ordinea componentelor fiind intern gestionarului.
Principala utilitate a acestui gestionar este utilizarea mai eficient a spaiului disponibil n
situaii n care componentele pot fi grupate n aa fel nct utilizatorul s interacioneze la un
moment dat doar cu un anumit grup (o carte din pachet), celelalte fiind ascunse.
Exemplu 5. Aplicaia arat modul de funcionare a unui CardLayout. Clasa TestCardLayout
particularizeaz clasa JFrame prin motenire. Sunt tratate evenimentele de click pe dou butoane
prin implementarea interfeei asculttor ActionListener.
// ontine si tratarea de evenimente pt. 2 butoane
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class TestCardLayout extends JFrame implements ActionListener {
JPanel tab;
public TestCardLayout() {
super("TestCardLayout");
JButton card1 = new JButton("Card 1");
JButton card2 = new JButton("Card 2");
JPanel butoane = new JPanel();

11

butoane.add(card1);
butoane.add(card2);
// partea care se va ascunde
JLabel et = new JLabel("Nume:");
JTextField text = new JTextField(20);
JPanel panel = new JPanel();
panel.add(et);
panel.add(text);
tab = new JPanel();
tab.setLayout(new CardLayout());
TextField tf = new TextField("Text Field");
tab.add("Card 1", tf);
tab.add("Card 2", panel);
add(butoane, BorderLayout.NORTH);
add(tab, BorderLayout.CENTER);
// adaugarea de ascultatoare pt. evenimente
card1.addActionListener(this);
card2.addActionListener(this);
pack();
}
public void actionPerformed(ActionEvent e) {
CardLayout gestionar = (CardLayout) tab.getLayout();
gestionar.show(tab, e.getActionCommand());
}
public static void main(String args[]) {
new TestCardLayout().setVisible(true);
}
}

Rezultatul acestui exemplu arata grafic astfel:

Gruparea componentelor (Clasa Panel)


Plasarea componentelor direct pe suprafaa de afiare poate deveni incomoda n cazul n
care avem multe obiecte grafice. Din acest motiv se recomanda gruparea obiectelor grafice nrudite
ca funcionalitate astfel nct sa putem fi siguri c, indiferent de gestionarul de poziionare al
suprafeei de afiare, ele se vor gsi mpreun. Gruparea componentelor se face n panel-uri.
Un panel este cel mai simplu model de container. El nu are o reprezentare vizibila, rolul sau
fiind de a oferi o suprafa de afiare pentru componente grafice, inclusiv pentru alte panel-uri.
Clasa care instaniaz aceste obiecte este Panel, extensie a superclasei Container. Pentru a aranja
corespunztor componentele grupate ntr-un panel, acestuia i se poate specifica un gestionar de
poziionare anume, folosind metoda setLayout. Gestionarul implicit pentru containerele de tip
Panel este FlowLayout.
Aadar, o aranjare eficienta a componentelor unei ferestre nseamn:
gruparea componentelor nfrite (care nu trebuie sa fie desprite de gestionarul de
poziionare al ferestrei) n panel-uri;
12

aranjarea componentelor unui panel, prin specificarea acestuia a unui gestionar de


poziionare corespunztor
aranjarea panel-urilor pe suprafaa ferestrei, prin specificarea gestionarului de
poziionare al ferestrei.

Exemplu 6.
import java.awt.*;
import javax.swing.*;
public class TestPanel {
public static void main(String args[]) {
JFrame f = new JFrame("Panel");
JPanel panel = new JPanel();
panel.setLayout(new FlowLayout());
panel.add(new JLabel("Text:"));
panel.add(new JTextField("", 20));
panel.add(new JButton("Reset"));
f.add(panel, BorderLayout.NORTH);
f.add(new JButton("OK"), BorderLayout.EAST);
f.add(new JButton("Cancel"), BorderLayout.WEST);
f.pack();
f.setVisible(true);
}
}

13

Evenimente n interfee grafice


ntr-o interfa grafic, eveniment este produs de o aciune a utilizatorului asupra unei
componente grafice i reprezint mecanismul prin care utilizatorul comunic efectiv cu programul.
Exemple de evenimente sunt: apsarea unui buton, modificarea textului ntr-un control de editare,
nchiderea, redimensionarea unei ferestre, etc. Componentele care genereaz anumite evenimente se
mai numesc i surse de evenimente.
Interceptarea evenimentelor generate de componentele unui program se realizeaz prin
intermediul unor clase de tip listener (asculttor, consumator de evenimente). In Java, orice
obiect poate consuma evenimentele generate de o anumita component grafic.
Utilizator
(aciune)

Component
(generare de eveniment)

Listener
(interceptarea evenimentului)

Aadar, pentru a scrie cod care s se execute n momentul n care utilizatorul interacioneaz cu o
componenta grafic trebuie sa facem urmtoarele lucruri:

s scriem o clasa de tip Listener care s asculte evenimentele produse de acea


component i n cadrul acestei clase s implementm metode specifice pentru tratarea lor;
s comunicm componentei surs c respectiva clas i ascult evenimentele pe care le
genereaz, cu alte cuvinte s nregistram acea clasa drept consumator al evenimentelor
produse de componenta respectiv.

Evenimentele sunt, ca orice altceva n Java, obiecte. Clasele care descriu aceste obiecte se
mpart n mai multe tipuri n funcie de componenta care le genereaz, mai precis n funcie de
aciunea utilizatorului asupra acesteia. Pentru fiecare tip de eveniment exist o clasa care instaniaz
obiecte de acel tip; de exemplu: evenimentul generat de acionarea unui buton este implementat prin
clasa ActionEvent, cel generat de modificarea unui text prin clasa TextEvent, etc.
Toate aceste clase au ca superclasa comuna clasa AWTEvent.
14

O clasa consumatoare de evenimente (listener) poate fi orice clasa care specifica n


declaraia sa ca dorete s asculte evenimente de un anumit tip. Acest lucru se realizeaz prin
implementarea unei interfee specifice fiecrui tip de eveniment. Astfel, pentru ascultarea
evenimentelor de tip ActionEvent clasa respectiv trebuie s implementeze interfaa
ActionListener, pentru TextEvent este TextListener, etc. Toate aceste interfee au
superinterfaa comun EventListener.
Se poate scrie ceva de forma:
class AscultaButoane implements ActionListener
class AscultaTexte implements TextListener

ntruct o clasa poate implementa oricte interfee ea va putea s asculte evenimente de mai multe
tipuri:
class Ascultator implements ActionListener, TextListener

Vom vedea n continuare metodele fiecrei interfee pentru a ti ce trebuie s implementeze


o clas consumatoare de evenimente.
Pentru ca evenimentele unei componente s fie interceptate de ctre o instan a unei clase
asculttor, aceast clas trebuie nregistrat n lista asculttorilor componentei respective.
nregistrarea unei clase n lista asculttorilor unei componente se face cu metode din clasa
Component de tipul addYYYListener, iar eliminarea ei din aceast list cu
removeYYYListener unde YYY reprezenta tipul evenimentului.
Exemplu 1. O fereastra care s conin doua butoane cu numele OK, respectiv Cancel. La
apsarea fiecrui buton se scrie pe bara de titlu a ferestrei mesajul Ati apasat butonul ...".
import java.awt.*;
import java.awt.event.*;
class Fereastra extends JFrame {
public Fereastra(String titlu) {
super(titlu);
//se stabileste gestionarul
setLayout(new FlowLayout());
//se dimensioneaza fereastra
setSize(300, 100);
//se construiesc si se adauga butoanele Ok si Cancel
JButton b1 = new JButton("OK");
add(b1);
JButton b2 = new JButton("Cancel");
add(b2);
//se construieste un obiect de tip Ascultator.
//la creare este pasata o referinta spre obiectul curent
//pt. ca ascultatorul sa aiba acces la elementle obiectului
//pe care a aparut evenimentul
Ascultator listener = new Ascultator(this);
//ambele butoane sunt ascultate de obiectul "listener"
//instanta a clasei Ascultator, definita mai jos
b1.addActionListener(listener);
b2.addActionListener(listener);
}
}

15

//implementarea ascultatotului pentru butoanele aplicatiei


class Ascultator implements ActionListener {
//atribut care va retine o referinta spre obiectul
//care contine butoanele tratate
private Fereastra f;
//constructorul Ascultatorului
public Ascultator(Fereastra f) {
this.f = f;
}
//metoda interfetei ActionListener (unica)
public void actionPerformed(ActionEvent e) {
//se afla comanda din obiectul de eveniment
String command = e.getActionCommand();
//numele comenzii este numele butonului apasat
System.out.println(e.toString());
if (command.equals("OK"))
f.setTitle("Ati apasat OK");
else
if (command.equals("Cancel"))
f.setTitle("Ati apasat Cancel");
}
}
public class ListenOkCancel { //fereastra principala
public static void main(String args[]) {
Fereastra f = new Fereastra("Evenimente pe 2 butoane");
f.setVisible(true);
}
}

Nu este obligatoriu s definim clase speciale pentru ascultarea evenimentelor. In exemplul


de mai sus am definit o clasa special Ascultator pentru a intercepta evenimentele produse de cele
doua butoane i din acest motiv a trebuit s trimitem ca parametru acestei clase instana la fereastr.
Mai uor ar fi fost s folosim chiar clasa Fereastra pentru a asculta evenimentele produse de
componentele ei:
class Fereastra extends JFrame implements ActionListener{
public Fereastra(String titlu) {
super(titlu);
. . .
//ambele butoane sunt ascultate chiar din clasa Fereastra
//deci ascultatorul este instanta curenta: this
b1.addActionListener(this);
b2.addActionListener(this);
}
public void actionPerformed(ActionEvent e) {
String command = e.getActionCommand();
System.out.println(e.toString());
if (command.equals("OK"))
this.setTitle("Ati apasat OK");
else
if (command.equals("Cancel"))
this.setTitle("Ati apasat Cancel");
}
}

16

Aadar, orice clas poate asculta evenimente de orice tip cu condiia s implementeze
interfeele specifice acelor evenimente.

Tipuri (clase) de evenimente si componentele care le genereaz


In tabelul de mai jos sunt prezentate n stnga tipurile de evenimente i interfeele iar n
dreapta lista componentelor ce pot genera evenimente de acel tip precum i o scurt explicaie
despre motivul care le provoac.
Eveniment/Interfa

Componente care genereaz acest eveniment


Button, List, TextField, MenuItem, CheckboxMenuItem, Menu,
PopupMenu
Aciuni asupra unui control
AdjustmentEvent
Scrollbar i orice clasa care implementeaz interfaa Adjustable
AdjustmentListener
Modificarea unei valori variind ntre doua limite
ComponentEvent
Component si subclasele sale
ComponentListener
Redimensionri, deplasri, ascunderi ale componentelor
ContainerEvent
Container si subclasele sale
ContainerListener
Adugarea, tergerea componentelor la un container
FocusEvent
Component si subclasele sale
FocusListener
Preluarea, pierderea focusului de ctre o componenta
KeyEvent
Component i subclasele sale
KeyListener
Apsarea, eliberarea unei taste cnd focusul este pe o anumita
componenta.
MouseEvent
Component si subclasele sale
MouseListener
Click, apsare, eliberare a mouse-ului pe o componenta, intrarea,
ieirea mouse-ului pe/de pe suprafaa unei componente
MouseEvent
Component si subclasele sale
MouseMotionListener Micarea sau drag-ul mouse-ului pe suprafaa unei componente
WindowEvent
Window si subclasele sale Dialog, FileDialog, Frame
WindowListener
nchiderea, maximizarea, minimizarea, redimensionarea unei ferestre
ItemEvent
Checkbox, CheckboxMenuItem, Choice, List i orice clasa care
ItemListener
implementeaza interfata ItemSelectable
Selecia, deselecia unui articol dintr-o lista sau meniu.
TextEvent
Orice clasa derivata din TextComponent cum ar fi : TextArea,
TextListener
TextField
Modificarea textului dintr-o componenta de editare a textului
ActionEvent
ActionListener

17

Evenimente suportate de o componenta


Urmtorul tabel prezint o clasificare a evenimentelor n funcie de componentele care le suport:
Componenta

Adjustable
Applet

Evenimente suportate de componenta

AdjustmentEvent
ContainerEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
Button
ActionEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
Canvas
FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Checkbox
ItemEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
CheckboxMenuItem ActionEvent, ItemEvent
Choice
ItemEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
Component
FocusEvent, KeyEvent, MouseEvent, ComponentEvent
Container
ContainerEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
Dialog
ContainerEvent, WindowEvent, FocusEvent, KeyEvent,
MouseEvent, ComponentEvent
FileDialog
ContainerEvent, WindowEvent, FocusEvent, KeyEvent,
MouseEvent, ComponentEvent
Frame
ContainerEvent, WindowEvent, FocusEvent, KeyEvent,
MouseEvent, ComponentEvent
Label
FocusEvent, KeyEvent, MouseEvent, ComponentEvent
List
ActionEvent, FocusEvent, KeyEvent, MouseEvent,
ItemEvent, ComponentEvent
Menu
ActionEvent
MenuItem
ActionEvent
Panel
ContainerEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
PopupMenu
ActionEvent
Scrollbar
AdjustmentEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
ScrollPane
ContainerEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
TextArea
TextEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
TextComponent
TextEvent, FocusEvent, KeyEvent, MouseEvent,
ComponentEvent
TextField
ActionEvent, TextEvent, FocusEvent, KeyEvent,
MouseEvent, ComponentEvent
Window
ContainerEvent, WindowEvent, FocusEvent, KeyEvent,
MouseEvent, ComponentEvent

18

Metodele interfeelor de tip listener


Orice clas care trateaz evenimente trebuie s implementeze obligatoriu metodele
interfeelor corespunztoare evenimentelor pe care le trateaz. Tabelul de mai jos prezint, pentru
fiecare interfaa, metodele puse la dispoziie i care trebuie implementate de clasa asculttor.
Interfata

ActionListener
AdjustmentListener
ComponentListener

Metodele interfetei

actionPerformed(ActionEvent)
adjustmentValueChanged(AdjustmentEvent)
componentHidden(ComponentEvent)
componentShown(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
ContainerListener
componentAdded(ContainerEvent)
componentRemoved(ContainerEvent)
FocusListener
focusGained(FocusEvent)
focusLost(FocusEvent)
KeyListener
keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
MouseListener
mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseMotionListener mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
WindowListener
windowOpened(WindowEvent)
windowClosing(WindowEvent)
windowClosed(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
ItemListener
itemStateChanged(ItemEvent)
TextListener
textValueChanged(TextEvent)

Folosirea adaptorilor i a claselor interne n tratarea evenimentelor


O clas care trateaz evenimente de un anumit tip trebuie sa implementeze interfaa
corespunztoare acelui tip. Aceasta nseamn ca trebuie s implementeze obligatoriu toate
metodele definite de acea interfa, chiar dac nu specific nici un cod pentru unele dintre ele. Sunt
ns situaii cnd acest lucru este suprtor, mai ales atunci cnd nu ne intereseaz dect o singur
metoda a interfeei.
Un exemplu sugestiv este urmtorul: o fereastra care nu are specificat cod pentru tratarea
evenimentelor sale nu poate fi nchisa cu butonul standard marcat cu 'x' din colul dreapta sus i nici
cu combinaia de taste Alt+F4. Pentru a realiza acest lucru trebuie interceptat evenimentul de
nchidere a ferestrei n metoda windoClosing i apelat apoi metoda dispose de nchidere a
ferestrei, eventual urmat de ieirea din program, n cazul cnd este vorba de fereastra principala a
aplicaiei. Aceasta nseamn c trebuie sa implementam interfaa WindowListener care are nu
mai puin de apte metode.

19

Exemplu 2. Crearea unei ferestre cu ascultarea evenimentelor sale folosind implementarea directa a
interfeei WindowListener.
import java.awt.*;
import java.awt.event.*;
class Fereastra extends JFrame implements WindowListener {
public Fereastra(String titlu) {
super(titlu);
this.addWindowListener(this);
}
//metodele interfetei WindowListener
public void windowOpened(WindowEvent e) {}
public void windowClosing(WindowEvent e) {
dispose();
//inchid fereastra
System.exit(0);
//termin programul
}
public void windowClosed(WindowEvent e) {}
public void windowIconified(WindowEvent e) {}
public void windowDeiconified(WindowEvent e) {}
public void windowActivated(WindowEvent e) {}
public void windowDeactivated(WindowEvent e) {}
}
public class TestWindowListener {
public static void main(String args[]) {
Fereastra f = new Fereastra("O fereastra");
f.setVisible(true);
}
}

Se observ c trebuie implementate toate metodele interfeei, chiar dac nu se scriem nici un
cod pentru ele. Singura metoda care intereseaz este windowClosing n care se specific ce
trebuie fcut atunci cnd utilizatorul dorete s nchid fereastra. Pentru a evita scrierea inutil a
acestor metode exista o serie de clase care implementeaz interfeele de tip listener far a
specifica nici un cod pentru metodele lor. Aceste clase se numesc adaptori.

Utilizarea adaptorilor
Un adaptor este o clasa abstracta care implementeaz o interfa de tip listener. Scopul
unei astfel de clase este ca la crearea unui asculttor de evenimente, n loc s implementeze o
anumita interfa i implicit toate metodele sale, se extinde adaptorul corespunztor interfeei
respective i se supradefinete doar metodele care intereseaz (cele n care se scrie o anumit
secven de cod).
De exemplu, adaptorul interfeei WindowListener este WindowAdapter iar folosirea
acestuia este data n exemplul de mai jos.

20

Exemplu 3. Crearea unei ferestre cu ascultarea evenimentelor sale folosind extinderea clasei
WindowAdapter.
import java.awt.*;
import java.awt.event.*;
class Fereastra extends JFrame {
public Fereastra(String titlu) {
super(titlu);
this.addWindowListener(new Ascultator());
}
}
class Ascultator extends WindowAdapter {
//suprdefinim metodele care ne intereseaza
public void windowClosing(WindowEvent e) {
//?.dispose();
// dispose nu se mai poate apela, de ce?
System.exit(0);
}
}
public class TestWindowAdapter {
public static void main(String args[]) {
Fereastra f = new Fereastra("O fereastra");
f.setVisible(true);
}
}

Avantajul clar al acestei modaliti de tratare a evenimentelor este reducerea codului


programului, acesta devenind mult mai uor lizibil. nsa exist i doua dezavantaje majore.
Dup cum ai observat, faa de exemplul anterior clasa Fereastra nu poate extinde
WindowAdapter deoarece ea extinde deja clasa Frame i din acest motiv s-a construi o
noua clasa numit Ascultator. Acest dezavantaj poate fi eliminat prin folosirea unei clase
interne.
Un alt dezavantaj este c orice greeala de sintax n declararea unei metode a interfeei nu
va produce o eroare de compilare dar nici nu va supradefini metoda interfeei ci, pur si
simplu, va crea o metoda a clasei respective.
class Ascultator extends WindowAdapter {
//exemple de erori sintactice:
// in loc de windowClosing scriem WindowClosing
// nu supradefinim vreo metoda a clasei WindowAdapter
// nu da nici o eroare
// nu face nimic !
public void WindowClosing(WindowEvent e) {
System.exit(0);
}
}

21

n tabelul de mai jos sunt dai toi adaptorii interfeelor de tip listener - se observ c o
interfa YYYListener are un adaptor de tipul YYYAdapter. Interfeele care nu au un adaptor sunt
cele care definesc o singura metoda i prin urmare crearea unei clase adaptor nu i are rostul.
Interfaa "listener"

ActionListener
AdjustmentListener
ComponentListener
ContainerListener
FocusListener
ItemListener
KeyListener
MouseListener
MouseMotionListener
TextListener
WindowListener

Adaptor

nu are
nu are
ComponentAdapter
ContainerAdapter
FocusAdapter
nu are
KeyAdapter
Mouse
MouseMotionAdapter
nu are
WindowAdapter

Folosirea claselor interne (anonime)


O clas interna este o clas declarata n cadrul altei clase iar clasele anonime sunt acele clase
interne folosite doar pentru instanierea unui singur obiect de acel tip. Un exemplu tipic de folosire
a lor este instanierea adaptorilor direct n corpul unei clase care conine componente ale cror
evenimente trebuie interceptate. Clasa Fereastra din exemplul anterior poate fi scrisa astfel:
class Fereastra extends JFrame {
public Fereastra(String titlu) {
super(titlu);
this.addWindowListener(new WindowAdapter() {
//corpul clasei anonime
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
}
}

Codul programului a fost redus substanial prin folosirea unui adaptor i a unei clase anonime.

22

Java GUI API --- Swing

23

24

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