curs 10 java

22
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

Upload: robert-visa

Post on 08-Sep-2015

35 views

Category:

Documents


2 download

DESCRIPTION

Curs 10 Java

TRANSCRIPT

Programare Java

Programare Java

Curs 10MANAGEMENTUL UNEI INTERFETE GRAFICEAspectul 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("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 )

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

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 . Schita noastra sa presupunem ca este ceva de genul :

La pasul urmator ar trebui sa tabelam deja interfata noastra etichetand celulele cu coordonatele lor x , y :

0,0 1,0

0,11,1

0,2 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 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 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