Programare Java

132
Programare Java Curs - 1 INSTRUCTIUNI SI EXPRESII Toate activitatile ce se realizeaza intr-un program Java pot fi rezumate la o serie de instructiuni . O instructiune ( statement ) este o comanda simpla , scrisa intr-un limbaj de programare si care determina o actiune . Instructiunile sunt actiuni elementare ale unui program Java . Mai jos putem vedem mai multe exemple de instructiuni Java simple : int varsta=30; import java.awt.dnd; System.out.println(“Text “); Jucator.scor=45000; Unele instructiuni produc o valoare , ca in cazul in care se aduna doua numere . Aceste instructiuni se numesc expresii . O expresie este o instructiune care are ca rezultat producerea unei valori . Valoarea poate fi pastrata pentru o folosire ulterioara in program , poate fi folosita imediat intr-o alta instructiune sau poate fi ignorata . Valoarea produsa de o instructiune este numita valoare de retur . Unele expresii produc o valoare de retur numerica , cum ar fi cazul cand se aduna doua numere ; altele produc valori booleene adevarat sau fals sau pot produce chiar un obiect Java . Chiar daca majoritatea programelor Java contin o singura instructiune pe fiecare linie aceasta este doar o optiune de formatare , care nu stabileste unde incepe si unde se termina o instructiune ci are scopul principal de a mari lizibilitatea programului . De fapt , fiecare instructiune Java se termina cu “ ; ” . Intr-o singura linie se pot introduce astfel mai multe instructiuni fara a determina probleme : j.culoare=”galben”; j.alegere=false; Instructiunile sunt grupate in Java folosind acoladele { si } . Un grup de instructiuni organizate intre acolade se numeste bloc . VARIABILE SI TIPURI DE DATE Variabilele reprezinta un loc unde poate fi pastrata informatia intr-un program aflat in executie . Valoarea poate fi modificata oricand in cadrul programului . Pentru a crea o variabila trebuie sa ii dati un nume si sa stabiliti ce tip de informatie va stoca . De asemenea , in momentul crearii puteti sa atribuiti variabilei o valoare initiala . Exista trei tipuri de variabile in Java : variabile de instanta , variabile de clasa si variabile locale . Variabilele de instanta sunt folosite pentru a defini atributele unui obiect . Variabilele de clasa definesc atributele unei intregi clase de obiecte si se aplica tuturor instantelor acesteia . Variabilele locale sunt folosite in interiorul definitiilor metodelor sau al blocurilor de instructiuni din cadrul unei metode . Ele pot fi folosite doar atunci cand metoda sau blocul este executat de interpretorul Java , dupa care isi inceteaza existenta . - 1 -

Transcript of Programare Java

Page 1: Programare Java

Programare Java

Curs - 1

INSTRUCTIUNI SI EXPRESII

Toate activitatile ce se realizeaza intr-un program Java pot fi rezumate la o serie de instructiuni .

O instructiune ( statement ) este o comanda simpla , scrisa intr-un limbaj de programare si care

determina o actiune .

Instructiunile sunt actiuni elementare ale unui program Java . Mai jos putem vedem mai multe exemple

de instructiuni Java simple :

int varsta=30;

import java.awt.dnd;

System.out.println(“Text “);

Jucator.scor=45000;

Unele instructiuni produc o valoare , ca in cazul in care se aduna doua numere . Aceste instructiuni se

numesc expresii .

O expresie este o instructiune care are ca rezultat producerea unei valori . Valoarea poate fi pastrata

pentru o folosire ulterioara in program , poate fi folosita imediat intr-o alta instructiune sau poate fi

ignorata . Valoarea produsa de o instructiune este numita valoare de retur .

Unele expresii produc o valoare de retur numerica , cum ar fi cazul cand se aduna doua numere ; altele

produc valori booleene – adevarat sau fals – sau pot produce chiar un obiect Java .

Chiar daca majoritatea programelor Java contin o singura instructiune pe fiecare linie aceasta este doar

o optiune de formatare , care nu stabileste unde incepe si unde se termina o instructiune ci are scopul

principal de a mari lizibilitatea programului .

De fapt , fiecare instructiune Java se termina cu “ ; ” . Intr-o singura linie se pot introduce astfel mai

multe instructiuni fara a determina probleme :

j.culoare=”galben”; j.alegere=false;

Instructiunile sunt grupate in Java folosind acoladele { si } . Un grup de instructiuni organizate intre

acolade se numeste bloc .

VARIABILE SI TIPURI DE DATE

Variabilele reprezinta un loc unde poate fi pastrata informatia intr-un program aflat in executie .

Valoarea poate fi modificata oricand in cadrul programului .

Pentru a crea o variabila trebuie sa ii dati un nume si sa stabiliti ce tip de informatie va stoca . De

asemenea , in momentul crearii puteti sa atribuiti variabilei o valoare initiala .

Exista trei tipuri de variabile in Java : variabile de instanta , variabile de clasa si variabile locale .

Variabilele de instanta sunt folosite pentru a defini atributele unui obiect .

Variabilele de clasa definesc atributele unei intregi clase de obiecte si se aplica tuturor instantelor

acesteia .

Variabilele locale sunt folosite in interiorul definitiilor metodelor sau al blocurilor de instructiuni din

cadrul unei metode . Ele pot fi folosite doar atunci cand metoda sau blocul este executat de

interpretorul Java , dupa care isi inceteaza existenta .

- 1 -

Page 2: Programare Java

Cu toate ca aceste trei tipuri de variabile sunt create asemanator , variabilele de clasa si de instanta sunt

folosite intr-un alt mod decat variabilele locale . In continuare vom trata variabilele locale – celelalte

doua tipuri vor fi detaliate mai tarziu .

OBS : Spre deosebire de alte limbaje Java nu are variabile globale ( utilizabile in orice parte a unui

program ) . Variabilele de clasa si de instanta sunt folosite pentru a comunica informatii despre un

obiect sau altul si pot inlocui nevoia de variabile globale .

Inainte de a folosi o variabila in Java trebuie mai intai sa o declaram prin indicarea numelui si a tipului

de informatie pe care il va stoca . Formatul declaratiei este prezentat in continuare , specificandu-se

intai tipul de informatie si apoi numele :

int maxim;

String numeutilizator;

boolean stareTerminare;

Variabilele locale pot fi declarate in orice loc in interiorul unei metode , la fel ca oricare alta

instructiune Java insa trebuie declarate inainte de a fi folosite . In mod normal declararea variabilelor

urmeaza imediat dupa instructiunea care defineste metoda .

Public static void main(String argumente[]) {

int total;

String titlu;

Boolean activare;

}

Daca vrem sa cream mai multe variabile de acelasi tip le putem declara pe toate in aceeasi instructiune ,

separate de “ , “ :

String strada , oras , tara ;

Variabilelor li se poate atribui o valoare atunci cand sunt create prin atribuire :

int codposta=7000;

String nume=”Alex”;

boolean alegere=true;

int varsta=50 , inaltime=170;

Dupa cum se poate vedea avem si posibilitatea de a atribui valori mai multor variabile de acelasi tip .

Variabilelor locale trebuie sa li se atribuie valori inainte de a fi folosite in program , altfel acestea nu se

vor compila .

Definitiile variabilelor de instanta si de clasa primesc o valoare initiala in functie de tipul informatiei pe

care o stocheaza :

- variabilele numerice : 0

- caracterele : “\0”

- variabilele booleene : false

- obiectele : null

Numele variabilelor in Java trebuie sa inceapa cu o litera , cu underscore ( “_” ) sau cu “ $ “ – ele nu

pot incepe cu o cifra . Dupa primul caracter numele variabilelor pot contine orice combinatie de cifre si

litere .

Trebuie sa retinem ca Java tine cont de litere mari si mici . Din aceasta cauza un program poate avea

doua variabile diferite : una numita X si alta x sau una alb si alta ALB .

In practica s-a impus o “regula” de denumire a variabilelor Java : numele sunt formate din cuvinte

sugestive iar in cazul in care sunt necesare mai multe cuvinte primul caracter al numelui este mic iar

inceputul fiecarui cuvant este scris cu majuscula , ca in exemplele de mai jos :

- 2 -

Page 3: Programare Java

Button incarcaFisier;

int codZona;

boolean definesteScorMaxim;

TIPURI DE VARIABILE

Dupa cum am vazut declaratia de variabila contine in afara numelui si tipul informatiei stocate . Acest

tip poate fi :

- un tip de date de baza

- numele unei clase sau interfete

- un tablou

In continuare prezentam tipurile de date de baza ale limbajului . Exista opt tipuri de baza pentru

stocarea intregilor , numerelor in virgula mobila , caracterelor si valorilor booleene . Aceste tipuri mai

sunt cunoscute si ca tipuri primitive deoarece fac parte integranta din limbajul Java si nu sunt obiecte ,

lucru care le face mai eficient de folosit . Aceste tipuri de date au aceeasi dimensiune si caracteristici

indiferent de sistemul de operare si de platforma folosita – spre deosebire de alte tipuri de date din alte

limbaje de programare .

Pentru stocare intregilor avem patru tipuri de date :

- byte - pe 8 biti - valori intre -128 si 127

- short - pe 16 biti - valori intre -32768 si 32767

- int - pe 32 biti - valori intre -2147483648 si 2147483647

- long - pe 64 biti - valori intre -9223372036854775808 si 9223372036854775807

Toate aceste tipuri sunt cu semn ceea ce inseamna ca pot stoca numere pozitive sau negative . Tipul

folosit pentru o variabila depinde de domeniul de valori de care este nevoie .

Un alt tip de numar ce poate fi stocat este cel reprezentat in virgula mobila ; pentru acestea exista

tipurile float si double . Numerele in virgula mobila sunt numerele care au o parte zecimala . Tipul float

este suficient in majoritatea cazurilor , pastrand numere intre 1,4E-45 si 3,4E38 . Daca totusi este

necesar se poate folosi tipul real double ce poate stoca numere intre 4,9E-324 si 1,7E308 .

Tipul char este folosit pentru caracterele individuale , cum ar fi litere , cifre , semne de punctuatie si

alte simboluri .

Ultimul dintre cele opt tipuri de baza este boolean . Spre deosebire de alte limbaje valorile pentru

variabilele de acest tip nu sunt 1 si 0 ci true si false .

Toate tipurile de variabile prezentate folosesc litere mici si asa trebuie folosite in cadrul programelor .

Exista clase care au aceleasi nume cu acestea , dar incep cu litera mare – de exemplu Boolean sau Char

. Aceste clase au alt rol in programarea Java astfel incat trebuie folosite diferit de tipurile de baza .

TIPURI DE CLASE

In afara celor opt tipuri de baza o variabila poate fi de tip clasa :

String numeDeFamilie=”Popescu”;

Culoare par;

Atunci cand o variabila are drept tip o clasa inseamna ca variabila refera un obiect al clasei respective

sau al uneia dintre subclasele sale . Referirea la o superclasa ca tip de variabila este folositoare atunci

cand variabila poate fi una dintre mai multe subclase diferite .

Declararea unei variabile de tip Object inseamna ca poate stoca orice obiect .

- 3 -

Page 4: Programare Java

OBS : Java nu are un echivalent al instructiunii typedef din C . Pentru a declara noi tipuri in Java se

declara o noua clasa iar variabilele pot folosi aceasta clasa drept tip .

Dupa ce o variabila a fost declarata i se poate da o valoare folosind operatorul de atribuire , “ = “ :

idCod=8546;

imbracatRapid=false;

COMENTARII

Una dintre metodele cele mai importante de crestere a lizibilitatii unui program este folosirea

comentariilor .

Comentariile reprezinta informatii introduse intr-un program doar in ajutorul persoanelor care incearca

sa-si dea seama ce anume se intampla in program . Compilatorul Java ignora total comentariile atunci

cand pregateste versiunea executabila a fisierului sursa Java .

Exista trei tipuri diferite de comentarii pe care le putem utiliza in programele Java .

Prima modalitate de a introduce comentarii in program este de a il prefixa cu doua simboluri slash “ //

“ . Orice incepe dupa aceste semne si pana la sfarsitul liniei este considerat comentariu :

int oreCredit=3; // defineste orele de credit pentru curs

Daca dorim sa introducem un comentariu care ocupa mai mult de un rand trebuie sa incepem cu

combinatia “ /* “ si sa incheiem cu combinatia “ */ “ .

Ultimul tip de comentariu este proiectat pentru a fi interpretabil si de catre calculator . Daca incepem

comentariul cu “ /** “ si il incheiem cu “ */ “ atunci comentariul este interpretat ca reprezentand

documentatia originala referitoare la functionarea clasei si a metodelor sale publice .

Acest tip de comentariu poate fi citit de utilitare ca JAVADOC din pachetul JDK . Acest utilitar

foloseste aceste comentarii pentru a crea un set de pagini web care documenteaza programul , ierarhia

sa de clase si metodele .

LITERALE

Literalele sunt numerele , textul si alte informatii care reprezinta direct o valoare .

Mai explicit , literalele reprezinta un termen apartinand programarii , care inseamna de fapt ca ceea ce

tastam este ceea ce vom obtine .

Java are mai multe literale pentru intregi . Numarul 4 de exemplu este un literal pentru tipul int . El

poate fi atribuit de asemenea variabilelor byte sau short deoarece el este suficient de “mic” si pentru

aceste doua tipuri . Un literal intreg mai mare decat poate stoca o variabila int este considerat automat

ca avand tipul long . Putem indica faptul ca un literal este un intreg de tip long prin adaugarea sufixului

L ( sau l ) . De exemplu urmatoarea instructiune stocheaza valoarea 4 intr-un intreg de tip long :

long totalPagini=4L;

Pentru a reprezenta o valoare negativa putem folosi literalul impreuna cu semnul minus ( “ – “ ) .

In Java putem folosi si literali in sistem octal sau hexazecimal . Pentru a folosi un literal intreg in octal

trebuie sa il prefixam cu cifra 0 ; numarul octal 777 trebuie astfel scris ca 0777 . Intregii hexazecimali

se folosesc prefixati cu 0x – ca de exemplu 0xFF .

- 4 -

Page 5: Programare Java

Literalele in virgula mobila folosesc caracterul punct pentru punctul zecimal . Toate literalele in virgula

mobila sunt automat considerate de tip double . Pentru a specifica tipul float adaugam F ( sau f ) – ca

mai jos :

float valoarePi=3.1415F;

Putem folosi si exponenti in literalele de virgula mobila folosind litera E ( sau e ) urmata de exponent :

double x=12e22;

doube y=19E-70;

Literalele caracter sunt exprimate printr-un singur caracter incadrat de ghilimele simple : „a‟ , „#‟ sau

„3‟ .

Unele caractere literale reprezinta caractere care nu sunt tiparibile sau accesibile pe tastatura . Mai jos

vom vedea coduri speciale care pot reprezenta aceste caractere speciale :

- \n = new line ( linie noua )

- \t = tab

- \b = backspace

- \r = revenire la capat de rand ( carriage return )

- \f = formfeed ( salt la pagina noua )

- \\ = semnul \

- \‟ = ghilimele simple

- \” = ghilimele duble

- \_ = octal

- \x_ = hexazecimal

- \u_ = caracter unicode ( standard pe 16 biti spre deosebire de ASCII standard care presupune

doar 128 de caractere )

In cazul ultimelor trei coduri se va inlocui in practica semnul “ _ “ cu un numar sau o cifra

hexazecimala .

Ultimele literale pe care le putem folosi intr-un program Java sunt sirurile de caractere . Un sir ( string )

in Java este un obiect si nu un tip de date primar . Sirurile nu sunt pastrate in tablouri ( ca in C de

exemplu ) . Deaorece sirurile sunt obiecte Java avem si metode care pot fi folosite pentru combinarea si

modificarea sirurilor precum si pentru a determina daca doua siruri au aceeasi valoare .

Literalele sir constau dintr-o serie de caractere incadrate intre ghilimele duble :

String autor=”Ion Popescu”;

String parola=”password”;

Sirurile pot contine si caractere speciale – prezentate anterior :

String exemplu=”Text intre ghilimele \”CITAT\””;

System.out.println(“Primul rand \n Al doilea rand”);

String titlu=”Invatati singuri Java\u2122”;

In ultima instructiune , secventa \u2122 produce simbolul “ TM “

( pe sistemele configurate sa suporte

Unicode ) .

Atunci cand se foloseste un literal sir Java stocheaza valoarea sa ca obiect String . Nu trebuie sa cream

explicit un nou obiect – ca in cazul celorlalte obiecte cu care vom lucra – deci este la fel de usor de

lucrat cu acest tip ca si cu tipurile primare . Sirurile sunt diferite in ceea ce priveste acest aspect – nici

unul dintre tipurile primare nu sunt pastrate ca obiecte atunci cand sunt folosite .

EXPRESII SI OPERATORI .

- 5 -

Page 6: Programare Java

O expresie reprezinta o instructiune care produce o valoare . Cele mai folosite expresii sunt cele

matematice – ca in continuare :

int x=3;

int y=4;

int z=x*y;

Ultima instructiune dintre cele de mai sus este o expresie . Operatorul de multiplicare * este folosit

pentru inmultirea dintre x si y iar rezultatul produs de expresie va fi pastrat intr-o variabila z de tip

intreg .

Valoarea produsa de o expresie este numita si valoare de retur . Aceasta valoare poate fi atribuita unei

variabile si folosita in diferite feluri in programele noastre .

Operatorii reprezinta simboluri speciale folosite in functii matematice , in unele tipuri de instructiuni

de atribuire sau in comparatii logice .

OPERATII ARITMETICE

In Java exista cinci operatori folositi pentru operatiile aritmetice de baza :

“ + “ Adunare

“ – “ Scadere

“ * “ Inmultire

“ / “ Impartire

“% “ Modulo

Fiecare operator de mai sus foloseste cate doi operanzi – cate unul de fiecare parte a operatorului .

Operatorul de scadere “ – “ poate fi folosit si pentru a nega un singur operator .

Un lucru care merita atentie sporita in ceea ce priveste operatorul de impartire este tipul operanzilor

folositi . Daca stocam rezultatul unei impartiri intr-un intreg acesta va fi rotunjit la un numar intreg

pentru ca tipul int nu poate lucra cu valori in virgula mobila . De exemplu expresia 21 / 5 are rezultatul

4 daca acesta este stocat intr-un int .

Impartirea modulo ( “ % “ ) produce ca rezultat restul impartirii . In expresia 21 / 5 rezultatul pe care il

vom obtine va fi 1 .

In general majoritatea operatiilor aritmetice cu intregi produc un rezultat de tip int indiferent de tipul

initial al operanzilor . Daca lucram cu alte tipuri – numere in virgula mobila sau intregi long – trebuie

sa ne asiguram ca operanzii au acelasi tip cu cel la care vrem sa ajungem .

Mai jos avem prezentat un exemplu care integreaza folosirea tuturor operatorilor aritmetici :

class Amoeba {

public static void main (String argumente[]) {

int x=6;

short y=4;

float a=.12f;

System.out.println("ati inceput cu " + x + " amoebe");

System.out.println("\tDoua s-au casatorit si partenerii lor s-au mutat la ele.");

x=x+2;

System.out.println("Aveti acum " + x);

System.out.println("\tSe declanseaza mitoza , care dubleaza numarul de amoebe.");

x=x*2;

System.out.println("Avem acum " + x);

System.out.println("\tIncepe o lupta. " + y + " amoebe pleaca.");

- 6 -

Page 7: Programare Java

x=x-y;

System.out.println("Avem acum " + x);

System.out.println("\tAtac al paramecilor ! Am pierdut o treime din colonie.");

x=x-(x/3);

System.out.println("Am ramas cu " + x + " amoebe");

System.out.println("Costul intretinerii zilnice per amoeba : " + a);

System.out.println("Costul total al intretinerii zilnice : " + (a*x));

}

}

Comentand pe scurt aceasta aplicatie Java extrem de simpla observam ca in liile 3- 5 se creaza trei

variabile ce primesc in acelasi timp si valori initiale ; variabilele x si y sunt declarate de tipul int iar

variabila a este declarata numar in virgula mobila float – deoarece tipul predefinit in Java pentru

numere in virgula mobila este double trebuie sa adaugam sufixul f la sfarsitul literalului pentru a indica

( si forta ) tipul float .

In cadrul programului apare in mai multe instructiuni sintagma “ System.out.println “ ; Aceasta metoda

este folosita in aplicatii pentru a afisa siruri si in general informatii pe dispozitivul standard de iesire –

in cele mai multe cazuri ecranul .

System.out.println() preia un singur argument ( intre paranteze ) : un sir . Pentru a prezenta mai mult de

o variabila sau un literal ca argument pentru println() se poate folosi operatorul + , pentru a concatena

aceste elemente intr-un singur sir .

ATRIBUIREA UNEI VALORI

Atribuirea este o expresie , ea producand un rezultat . In practica atribuirea poate apare intr-un sir de

instructiuni :

x=y=z=10;

Rezultatul acestei instructiuni este initializarea celor trei variabile cu valoarea 10 .

Partea din dreapta a unei expresii de atribuire este intotdeauna calculata inainte de a avea loc atribuirea

propriu-zisa . Acest lucru face posibila folosirea unei expresii de felul urmator :

int x=5;

x=x+2;

Logic se calculeaza intai x+2 , rezultatul fiind 7 si apoi aceasta valoare este atribuita variabilei x .

Atribuirea este operatia cea mai des intalnita in programare si in consecinta au aparut mai multi

operatori speciali pentru diferite cazuri de atribuire . Mai jos vom vedea operatorii de atribuire speciali

precum si echivalentele functionale ale acestora :

X+=Y X=X+Y

X-=Y X=X-Y

X*=Y X=X*Y

X/=Y X=X/Y

Acesti operatori de atribuire sunt echivalenti perfect cu instructiunile pe care le inlocuiesc dar trebuie

avuta mare atentie la utilizarea lor ; in cazul folosirii acestor operatori in cadrul unor expresii mai

complexe exista cazuri in care acesti operatori nu mai sunt echivalenti . Ca exemplu putem lua situatia

urmatoare :

X=20; Y=5;

X=X/Y+5; si

X/=Y+5;

- 7 -

Page 8: Programare Java

Rezultatele celor doua instructiuni vor fi diferite : in primul caz rezultatul va fi 9 iar in cel de-al doilea

2 .

INCREMENTAREA SI DECREMENTAREA

O alta operatie uzuala in programare este adaugarea sau scaderea unei unitati dintr-o variabila intreaga .

Exista operatori speciali pentru aceste expresii – operatori numiti de incrementare si decrementare .

Incrementarea unei variabile inseamna a adauga 1 la valoarea sa iar decrementarea unei variabile

inseamna a scadea 1 din valoarea sa .

Operatorul de incrementare este “ ++ “ iar cel pentru decrementare este “ – “ . Acesti operatori sunt

plasati imediat inainte sau dupa numele unei variabile :

int X=7;

X=X++;

In exemplul de mai sus variabila X este incrementata de la 7 la 8 .

In cazul in care operatorii de incrementare sau decrementare sunt plasati inaintea variabilei atunci ei se

numesc operatori prefix iar in cazul in care apar dupa variabila se numesc operatori sufix .

Intr-o expresie simpla , de exemplu variabila-- , folosirea unui operator prefix sau sufix nu schimba

rezultatul . Atunci cand operatiunile de incrementare sau decrementare fac parte dintr-o expresie mai

complexa optiunea intre prefix si sufix devine importanta .

Sa comentam putin exemplul de mai jos :

int x,y,z;

x=42; y=x++ ; z=++x ;

Aceste doua expresii produc rezultate diferite din cauza diferentelor intre operatorii sufix si prefix .

Atunci cand folosim operatori sufix , ca in y=x++ , variabila y primeste valoarea lui x inainte ca aceasta

sa creasca cu 1 astfel incat y va fi egal cu 42 ; la folosirea operatorilor prefix , ca in z=++x , variabila x

este mai intai incrementata si apoi valoarea sa este atribuita lui y , astfel incat z va avea valoarea 44 .

Ca si incazul operatorilor speciali de atribuire trebuie avuta mare grija in cazul folosirii operatorilor de

incrementare si decrementare in cazul unor expresii mai complexe – existand posibilitatea introducerii

unei erori destul de greu de depistat in cadrul programului .

OPERATORI PENTRU COMPARATII

Java poseda mai multi operatori folositi pentru a face comparatii intre variabile , intre variabile si

literale sau intre alte tipuri de informatie dintr-un program Java .

Acesti operatori sunt folositi in expresii care intorc valori booleene true si false , in functie de valoarea

de adevar a comparatiei .

In cele ce urmeaza prezentam operatorii de comparatie uzitati in Java :

Operator Semnificatie Exemplu

== egal x==3

!= diferit x!=3

< mai mic decat x<3

> mai mare decat x>3

<= mai mic sau egal cu x<=3

- 8 -

Page 9: Programare Java

>= mai mare sau egal cu x>=3

In continuare avem un exemplu practic de folosire a unei comparatii :

boolean tanar;

int varsta=41;

tanar=varsta<35;

Expresia varsta<35 produce rezultatul true sau false ( in cazul nostru false ) in functie de valoarea

variabilei varsta . In final valoarea variabilei “ tanar “ va fi astfel false .

OPERATORI LOGICI

Expresiile care produc valori booleene ( cum ar fi comparatiile ) pot fi combinate pentru a forma

expresii mai complexe . Acest lucru poate fi realizat folosind operatorii logici . Acesti operatori pot fi

folositi pentru combinatii logice AND ( si ) , OR ( sau ) , XOR ( sau exclusiv ) si NOT ( negare ) .

Pentru combinatiile AND se folosesc operatorii logici & si && . Atunci cand doua expresii booleene

sunt conectate prin operatorii & sau && expresia combinata returneaza valoarea true doar daca ambele

expresii booleene au valoarea true .

Diferenta intre & si && consta in modul in care Java evalueaza expresia combinata . Daca se foloseste

& atunci se evalueaza ambele expresii indiferent de valoarea lor . Daca se foloseste && si expresia din

stanga operatorului are valoarea de adevar false atunci expresia din dreapta operatorului nu mai este

evaluata deoarece rezultatul final va fi oricum false .

Pentru combinatiile OR se folosesc operatorii | sau || . Aceasta combinatie de expresii intoarce valoarea

true daca cel putin una dintre expresiile booleene este adevarata .

In cazul folosirii operatorului || , daca prima expresie booleena are valoarea true atunci a doua nici nu

se mai evalueaza , rezultatul final fiind oricum true .

Combinatia XOR foloseste un singur simbol : “ ^ “ . Acesta are ca rezultat o valoare true numai daca

ambele expresii booleene pe care le combina au valori diferite . In cazul in care ambele expresii au

valoarea true sau ambele false atunci rezultatul va fi false .

Combinatia NOT foloseste operatorul logic “ ! “ , urmat de o singura expresie . Acesta schimba

valoarea unei expresii booleene in acelasi fel in care simbolul “ – “ schimba semnul pozitiv sau negativ

al unui numar .

PRECEDENTA OPERATORILOR

Atunci cand intr-o expresie se folosesc mai multi operatori Java are stabilita o anumita ordine in care ii

evalueaza . In majoritatea cazurilor aceasta precedenta determina valoarea finala a expresiei .

In general , ordinea operatiilor este urmatoarea :

- operatii de incrementare si decrementare

- operatii aritmetice

- comparatii

- operatii logice

- expresii de atribuire

Daca doua operatii au aceeasi precedenta , cea aflata mai in stanga expresiei va fi calculata prima .

In tabelul de mai jos avem prezentata precedenta operatorilor :

- 9 -

Page 10: Programare Java

. [] () Parantezele rotunde se folosesc pentru a grupa

expresii ; punctul se foloseste pentru a accesa

metodele si variabilele din cadrul obiectelor si

claselor ; parantezele drepte sunt folosite pentru

tablouri .

++ -- ! instanceof Instanceof intoarce valoarea true sau false daca

obiectul este sau nu o instanta a clasei numite sau

a unei subclase a acesteia

new (tip) expresie Operatorul new este folosit pentru crearea de noi

instante ale claselor ; in acest caz se foloseste

pentru transformarea unei valori intr-un alt tip

* / % Inmultire , impartire , modulo

+ - Adunare , scadere

<< >> >>> Deplasarea pe biti la stanga si la dreapta

< > >= <= Comparatii

== != Teste de egalitate

& AND

^ XOR

| OR

&& AND optimizat ( logic )

|| OR optimizat ( logic )

?: Operatorul conditional

= += -= *= /= %= Atribuiri

In cazul in care nu suntem siguri de precedenta diferitiolor operatori cea mai buna solutie este folosirea

parantezelor pentru a impune precedenta dorita .

ARITMETICA SIRURILOR

Operatorul “ + “ este folosit nu doar pentru calcule matematice ci si pentru a concatena siruri .

Operatorul “ + “ concateneaza siruri , alte obiecte si variabile pentru a forma un singur sir .

Pentru a adauga ceva la sfarsitul unui sir se poate folosi si operatorul “ += “ , ca in exemplul urmator :

numeleMeu +=” Jr.”;

Instructiunea anterioara este bineinteles echivalenta cu :

numeleMeu=numeleMeu + “ Jr.”;

- 10 -

Page 11: Programare Java

Programare Java

Curs – 2

TABLOURI

Tablourile reprezinta o modalitate de a pastra o lista de elemente cu aceleasi tipuri de

date primitive sau de clase . Fiecare element al listei este pastrat intr-o locatie proprie ,

numerotata astfel incat informatia poate fi usor accesata .

Tablourile pot contine orice tip de informatie pastrata in mod normal intr-o variabila ,

insa , o data creat , tabloul nu poate fi folosit decat pentru acel tip de date . De

exemplu , putem avea un tablou de intregi , un tablou de obiecte String sau un tablou

de tablouri insa nu putem avea un tablou care sa contina atat siruri cat si intregi .

Pentru a crea un tablou in Java trebuie sa urmarim pasii de mai jos :

1. Declaram o variabila care sa refere un tablou

2. Cream un obiect de tip tablou si il atribuim variabilei tablou

3. Stocam informatia in tabloul respectiv

DECLARAREA VARIABILELOR TABLOU

Primul pas de mai sus este declararea variabilei care va referi tabloul . Variabilele

tablou indica tipul de obiecte sau de date pe care le va contine tabloul , precum si

numele acestuia . Pentru a le diferentia de declaratiile normale de variabile se adauga

o pereche de paranteze patrate [] la tipul de obiecte sau de date sau la numele

variabilei .

Exemplu :

String cuvinte[];

Point lovituri;

int salariu[];

Exemplele de mai jos sunt si ele valide :

String[] cuvinte;

Point[] lovituri;

int[] salariu;

CREAREA DE OBIECTE TABLOU

Dupa ce declaram variabila tablou , urmatorul pas este de a crea un obiect tablou si de

a-l atribui unei variabile . Exista mai multe modalitati :

- 11 -

Page 12: Programare Java

- folosim operatorul new

- initializam direct continutul tabloului

Deoarece tablourile sunt obiecte Java putem folosi operatorul new pentru a crea o

noua instanta a unui tablou :

String[] numeJucatori=new String[10];

Aceasta instructiune creaza un tablou de siruri cu 10 pozitii , care poate contine

obiecte String . Atunci cand cream un obiect tablou folosind operatorul new , trebuie

sa indicam cate pozitii urmeaza sa contina acesta . Aceasta instructiune nu introduce

nici un fel de obiecte String pe aceste pozitii .

Obiectele tablou pot contine si tipuri primitive cum ar fi intregi sau valori booleene ,

nu numai obiecte :

int[] temp=new int[99];

Atunci cand cream un obiect tablou folosind operatorul new toate pozitiile sale vor fi

initializate automat ( cu 0 cele numerice , cu false pentru boolean , cu „/0‟ pentru tipul

caracter si cu null pentru obiecte ).

OBS : null nu este echivalent cu zero sau cu caracterul “/0” , ca in cazul limbajului C

Putem crea si initializa un tablou in acelasi timp . In loc sa folosim operatorul new

pentru a crea noul obiect tablou includem elementele tabloului intre {} , separate prin

virgula :

String[] nume={“Ion” , “Andrei”, “Mihai” };

Fiecare dintre elementele dintre acolade trebuie sa fie de acelasi tip cu variabila tablou

. Atunci cand cream un tablou cu valori initiale in acest fel , tabloul are dimensiunea

egala cu numarul de elemente incluse . Exemplul anterior creaza un tablou de obiecte

String , denumit nume , care contine trei elemente .

ACCESAREA ELEMENTELOR TABLOULUI

Dupa ce s-a creat un tablou cu valori initiale putem accesa , modifica si testa valorile

fiecarei locatii a acestuia . Valoarea unei locatii este accesata cu numele tabloului ,

urmat de pozitia ei in cadrul acestuia , incadrata intre [] . Numele si pozitia pot fi

folosite intr-o expresie , cum ar fi :

scorParticipant[40]=500;

scorParticipant reprezinta o variabila care refera un obiect tablou . Pozitia ( indexul )

specifica locatia care va fi accesata in cadrul tabloului Numerotarea pozitiilor incepe

de la 0 astfel incat un tablou cu 10 elemente poate fi accesat folosind pozitiile 0 – 9 .

- 12 -

Page 13: Programare Java

Toate pozitiile unui tablou sunt verificate daca se incadreaza in limitele tabloului asa

cum s-au specificat la crearea tabloului . In Java este imposibil sa accesam sau sa

atribuim o valoare unei pozitii a tabloului aflata in afara limitelor sale , problema care

aparea in C de exemplu .

String[] vorbitor=new String[10];

vorbitor[10] =”Text introdus”;

Un program care foloseste aceste doua linii de cod va da eroare de compilare la

folosirea variabilei vorbitor[10] . Eroarea apare din cauza ca tabloul nostru nu poseda

pozitia a zecea .

Pentru a evita in programe depasirea accidentala a sfarsitului tabloului putem folosi o

variabila de instanta length – disponibila pentru toate obiectele tablou , indiferent de

tip :

int lungime=lungime.length;

MODIFICAREA ELEMENTELOR TABLOURILOR

Dupa cum am vazut mai sus putem atribui o valoare unei anumite pozitii a tabloului

prin introducerea operatorului de atribuire dupa numele tabloului si al indexului :

noteleMele[4]=10;

propozitia[0]=”Aici”;

propozitia[10]=propozitia[0];

Un lucru important de retinut este ca un tablou de obiecte , in Java , este un tablou de

referinte la obiectele respective . Atunci cand atribuim o valoare unei pozitii dintr-un

astfel de tablou nu se va copia valoarea dintr-o pozitie in alta ci se va atribui referinta .

In schimb , tablourile de tipuri de date primitive copiaza valorile dintr-o locatie in alta

.

Tablourile sunt relativ simplu de creat si modificat insa ofera foarte multe avantaje si

sunt foarte utile in Java .

1: class TestTablou {

2:

3: String[] prenume={“Dennis”,”Grace”,”Bjarne”,”James”};

4: String[] numeDeFamilie=new String[prenume.length];

5:

6: void afiseazaNume() {

7: int i=0;

8: System.out.println(prenume[i]

9: +” “ +numeDeFamilie[i]);

10 i++;

11. System.out.println(prenume[i]

- 13 -

Page 14: Programare Java

12: +” “ +numeDeFamilie[i]);

13 i++;

14. System.out.println(prenume[i]

15: +” “ +numeDeFamilie[i]);

16 i++;

17. System.out.println(prenume[i]

18: +” “ +numeDeFamilie[i]);

19 }

20:

21: public static void main (String argumente[]) {

22: TestTablou a=new TestTablou();

23: a.afiseazNume();

24: System.out.println(“____”);

25: a.numeDeFamilie[0]=”Ritchie”;

26: a.numeDeFamilie[1]=”Hopper”;

27: a.numeDeFamilie[2]=”Stroustrup”;

28: a.numeDeFamilie[3]=”Gosling”;

29: a.afiseazaNume();

30: }

31: }

In acest program cream o clasa TestTablou , cu doua variabile de instanta care

pastreaza tablouri de obiecte String . Primul , prenume , este declarat si initializat in

linia 3 pentru a contine patru siruri . A doua variabila , numeDeFamilie , este

declarata si creata in linia 4 , insa nu contine nici o valoare initiala . Tabloul acesta are

acelasi numar de pozitii ca si tabloul prenume , deoarece foloseste valoarea

prenume.length . Atunci cand este folosita pentru un obiect tablou , variabila de

instanta length intoarce numarul de pozitii din tablou .

Clasa TestTablou mai contine si doua metode : afiseazaNume si main . Metoda

afiseazaNume() , definita in liniile 6 – 19 , parcurge succesiv tablourile prenume si

numeDeFamilie , afisand continutul fiecarei pozitii .

Metoda main creaza o instanta initiala a clasei TestTablou ( in linia 22 ) asa incat sa I

se poata folosi variabilele si metodele de instanta .

Linia 23 apeleaza metoda afiseazaNume() , pentru a prezenta cum arata initial

obiectul . Rezultatul este dat in primele patru linii afisate .

Liniile 25 – 28 seteaza valorile fiecarei pozitii din tabloul numeDeFamilie .

Linia 29 apeleaza inca o data metoda afiseazaNume() pentru a arata noile valori din

tabloul numeDeFamilie .

TABLOURI MULTIDIMENSIONALE

Dimensiunile multiple ale unui tablou sunt folositoare atunci cand reprezentam de

exemplu un tabel x,y de elemente ale unui caroiaj .

- 14 -

Page 15: Programare Java

Java nu suporta tablourile multidimensionale , insa obtine acelasi efect prin declararea

unui tablou de tablouri . Acele Tablouri pot contine si ele tablouri si asa mai departe ,

pana cand este obtinut numarul de dimensiuni dorit .

Mai jos avem un exemplu de declarare si accesare a unor astfel de tablouri :

int[][] coordonate=new int[12][12];

coordonate[0][0]=1;

coordonate[0][1]=2;

INSTRUCTIUNI BLOC

Instructiunile din Java sunt grupate in blocuri . Inceputul si sfarsitul unui bloc sunt

notate cu acolade {} .

Blocurile sunt denumite si instructiuni bloc , deoarece un bloc poate fi folosit oriunde

poate fi folosita o instructiune simpla . Fiecare instructiune din cadrul blocului se

executa secvential .

Blocurile pot fi plasate si in cadrul altor blocuri , asa cum se procedeaza la

introducerea unei metode in cadrul unei definitii de clasa .

Un lucru de retinut referitor la blocuri este acela ca ele creaza un domeniu de

vizibilitate pentru variabilele locale create in cadrul blocului .

Domeniu de vizibilitate este un termen folosit in programare pentru a denumi acea

parte a programului in care o variabila exista si poate fi folosita . Daca programul

paraseste domeniul de vizibilitate al unei variabile , aceasta nu mai exista si incercarea

de a o accesa va da nastere unei erori .

Domeniul de vizibilitate al unei variabile este blocul in care a fost creata . Atunci cand

cream si folosim variabile locale in cadrul unui bloc , aceste variabile isi inceteaza

existenta dupa ce blocul isi termina executia .

void testBloc() {

int x=10;

{ // incepere bloc

int y=40;

y=y+x;

} // sfarsit bloc

}

In exemplul anterior exista doua variabile definite in cadrul acestei metode : x si y .

Domeniul de vizibilitate al variabiley y este blocul in care se afla ; ea poate fi folosita

doar in cadrul acestui bloc . Daca am incerca sa o folosim oriunde in alta parte a

metodei testBloc() vom obtine o eroare . Variabila x a fost creata in interiorul metodei

, insa in afara blocului interior , deci poate fi folosita in orice alta parte a metodei .

Putem modifica valoarea lui x oriunde in cadrul metodei .

- 15 -

Page 16: Programare Java

INSTRUCTIUNEA CONDITIONALA IF

Unul dintre aspectele cheie ale programarii este posibilitatea unui program de a decide

ce va face . Acest lucru este tratat printr-un tip special de instructiuni denumite

instructiuni conditionale .

O instructiune conditionala reprezinta o instructiune executata doar in cazul

indeplinirii unei anumite conditii .

Cea mai des folosita instructiune conditionala este IF ( daca ) . Aceasta foloseste o

expresie booleana pentru a decide daca o instructiune va fi sau nu executata . Daca

expresia intoarce valoarea true instructiunea se va executa .

if (varsta>50)

System.out.println(“Nu mai esti chiar tanar”);

Daca dorim ca atunci cand expresia IF intoarce valoarea false sa se execute totusi

ceva folosim cuvantul cheie optional else .

if (alegere==true)

restaurant=”President”;

else

restaurant=”Lido”;

Expresia IF executa instructiuni diferite in functie de rezultatul unei singure testari

booleene .

OBS : Testul instructiunii IF in Java trebuie sa returneze o variabila booleana ( true

sau false ) ; in C testul poate returna un intreg .

In practica se foloseste si o versiune prescurtata a testului conditional IF ; in locul

expresiei :

if (alegere==true)

Putem folosi doar :

if (alegere)

In continuare vom vedea un exemplu complet de aplicatie Java care se bazeaza pe

folosirea testului IF :

1: class TestParitate {

2:

3: void verificareParitate(int val) {

4: System.out.println(“Valoarea este “

5: +val+”. “);

6: if (val%2==0)

- 16 -

Page 17: Programare Java

7: System.out.println(“Par”);

8: }

9:

10: public static void main (String argumente[]) {

11. TestParitate e=new TestParitate();

12:

13: e.verificareParitate(1);

14: e.verificareParitate(2);

15: e.verificareParitate(54);

16: e.verificareParitate(77);

17: e.verificareParitate(1346);

18: }

19: }

“Nucleul” clasei TestParitate este metoda verificareParitate() – liniile 3-8 – in care

valorile sunt testate si se tipareste mesajul corespunzator . Metoda incepe prin

tiparirea valorii care i-a fost transmisa . Argumentul este apoi testat folosind o

instructiune conditionala IF , pentru a verifica daca un numar este par .

Metoda main() a aplicatiei creaza o noua instanta a clasei TestParitate si o testeaza

apeland metoda verificareParitate() de mai multe ori , cu diferite valori .

OPERATORUL CONDITIONAL

O alternativa viabila in practica este folosirea intr-o instructiune conditionala , in locul

cuvintelor cheie IF si ELSE a operatorului conditional ( numit si operator ternar –

deoarece are trei termeni ) .

Operatorul conditional este o expresie , ceea ce inseamna ca intoarce o valoare , spre

deosebire de mai generalul IF care are ca rezultat doar executarea unei instructiuni .

Operatorul conditional este mai util pentru instructiuni conditionale scurte sau simple

, ca in exemplul urmator :

test?rezultat_adevarat:rezultat_fals;

test este o expresie care intoarce true sau false , la fel ca testul din instructiunea IF .

Daca testul este adevarat ( true ) operatorul conditional intoarce valoarea

rezultat_adevarat iar daca este fals returneaza rezultat_fals .

Mai jos putem vedea un exemplu practic :

int celMaiBunScor=scorulMeu>scorulTau?scorulMeu:scorulTau;

Folosirea operatorului conditional este echivalentul urmatorului cod IF :

int celMaiBunScor;

if (scorulMeu>scorulTau) celMaiBunScor=scorulMeu;

else celMaiBunScor=scorulTau;

- 17 -

Page 18: Programare Java

Operatorul conditional are o precedenta foarte scazuta – este de obicei evaluat dupa

toate subexpresiile sale . Singurii operatori care au precedenta mai mica sunt cei de

atribuire .

INSTRUCTIUNEA SWITCH

O operatie des intalnita in orice limbaj este compararea unei variabile cu o anumita

valoare , apoi compararea cu o alta in caz ca nu se potriveste cu prima si asa mai

departe . Acest proces poate deveni destul de dificil daca s-ar folosi doar instructiuni

IF , in functie de diversitatea valorilor pe care trebuie sa le comparam . De exemplu

putem ajunge la un set de instructiuni de genul :

if (oper==‟+‟) adunaArg(arg1,arg2);

else if (oper==‟-„) scadeArg(arg1,arg2);

else if (oper==‟*‟) inmultireArg(arg1,arg2);

else if (oper==‟/‟) imparteArg(arg1,arg2);

Folosirea IF-ului in acest caz este o imbricare deoarece fiecare instructiune else

contine o alta if pana se fac toate testele posibile .

Un mecanism prescurtat pentru aceste instruciuni IF imbricate , care poate fi folosit in

unele limbaje de programare , este gruparea testelor si actiunilor intr-o singura

instructiune . In Java putem grupa actiunile – ca si in C – folosind instructiunea

SWITCH .

switch(nota) {

case 10: System.out.println(“Foarte bine”); break;

case 8: System.out.println(“Bine”);break;

case 5: System.out.println(“Ai trecut”);break;

default: System.out.println(“4 - ai cazut”);

}

Instructiunea SWITCH este bazata pe un test ; in exemplul nostru se testeaza variabila

nota . Variabila testata , care poate fi de orice tip primitiv ( byte , short , char sau int )

este comparata pe rand cu fiecare dintre valorile case . Daca se gaseste o potrivire se

executa instructiunea specificata dupa test ; daca nu se gaseste nici o potrivire se

executa instructiunea default . Aceasta instructiune este de fapt optionala ; daca este

omisa si nu se gaseste nici o potrivire case atunci instructiunea SWITCH se incheie

fara a se executa nimic .

Implementarea Java a instructiunii SWITCH este oarecum limitata – testele si valorile

pot fi doar tipuri primitive simple ce pot fi convertite in int . Intr-o asemenea

instructiune nu se pot folosi tipuri primitive de dimensiuni mai mari – large sau float –

siruri sau alte obiecte si nici nu se pot testa alte relatii in afara de cea de egalitate .

Aceste restrictii limiteaza folosirea SWITCH la cazuri relativ simple . In schimb

instructiunile IF imbricate pot fi folosite pentru orice tip de testare .

- 18 -

Page 19: Programare Java

Trebuie sa mentionez ca dupa o instructiune case putem include oricate instructiuni

fara a fi necesare acoladele ( ca in cazul lui IF ) .

Instructiunea break forteaza iesirea din instructiunea SWITCH la gasirea unei potriviri

de valoare . Exista posibilitatea nefolosirii acestei instructiuni – caz in care programul

executa mai departe instructiunile pana intalneste un break sau pana la sfarsitul

instructiunii switch . Instructiunea break intrerupe executia in punctul curent si face

un salt la codul aflat dincolo de urmatoarea acolada inchisa } .

Avantajul nefolosirii lui break apare atunci cand se doreste executarea acelorasi

instructiuni pentru mai multe valori . Pentru aceasta se folosesc mai multe linii case

fara instructiuni ; astfel , switch va executa primele instructiuni pe care le va intalni .

De exemplu , in urmatoarea instructiune switch sirul „x este un numar par‟ este afisat

doar daca x are una dintre valorile 2 , 4, 6 sau 8 . Toate celelalte valori ale lui x duc la

afisarea textului default :

switch(x) {

case 2:

case 4:

case 6:

case 8:

system.out.println(“x este un numar par”);

break;

default: System.out.println(“x nu este par”);

}

In cele ce urmeaza vom detalia inca un exemplu care foloseste instructiunea SWITCH

. Aceasta clasa converteste valorile intregi in cuvintele ce le denumesc .

class CititorNumere{

String conversieNumar(int val) {

switch (val) {

case 0: return “zero”;

case 1: return “unu”;

case 2: return “doi”;

case 3: return “trei”;

case 4: return “patru”;

case 5: return “cinci”;

case 6: return “sase”;

case 7: return “sapte”;

case 8: return “opt”;

case 9: return “noua”;

default: return “ “;

}

}

public static void main(String argumente[]) {

CititorNumere n=new CititorNumere();

String num=n.conversieNumar(4)+n.conversieNumar(1)+n.conversieNumar(3);

System.out.printl(“413 este convertit in : “+num);

}

}

- 19 -

Page 20: Programare Java

Instructiunea switch preia un argument intreg care este transmis metodei

conversieNumar() care , daca gaseste o potrivire , intoarce valoarea corespunzatoare

sub forma de sir .

Nu este nevoie de instructiuni break in CititorNumere deoarece se foloseste in schimb

instructiunea return . Aceasta este asemanatoare cu break , deosebirea fiind ca return

iese definitiv din metoda si returneaza o valoare .

CICLURI FOR

Ciclurile for repeta o instructiune de un numar specificat de ori , pana in momentul

cand se intalneste o conditie . Chiar daca sunt folosite de obicei pentru simple iteratii ,

in care o instructiune este repetata de un numar de ori , ciclurile for pot fi folosite

pentru orice tip de operatii repetitive .

Ciclul for arata in Java ca mai jos :

for ( initializare; test; incrementare) {

instructiune; }

Inceputul ciclului for contine trei parti :

- initializare este o expresie care initializeaza pornirea ciclului . Daca folosim o

variabila index a ciclului aceasta expresie o poate declara si initializa in acelasi

timp . Variabilele declarate in for sunt locale ciclului in sine . In acesta

sectiune se pot initializa mai multe variabile , separand fiecare expresie printr-

o virgula .

- test este testul care se face dupa fiecare parcurgere a ciclului . Testul trebuie sa

fie o expresie booleana sau o functie care returneaza o valoare booleana , cum

ar fi i<10 . Daca testul este true ciclul isi continua executia . O data intoarsa

valoarea false ciclul isi intrerupe executia .

- incrementarea este o expresie sau un apel de functie . De obicei incrementarea

este folosita pentru a modifica valoarea indexului ciclului , pentru a aduce

starea ciclului mai aproape de final . Asemanator sectiunii initializare , putem

specifica aici mai multe expresii , separate prin virgule .

In exemplul de mai jos putem vedea o instructiune for care atribuie tuturor pozitiilor

unui tablou String valoarea Dl. :

String[] formulSalut=new String[10];

int i;

for (i=0;i<formulaSalut.length;i++)

formulaSalut[i]=”Dl. ”;

Elementul final al instructiunii for este expresia i++ ; aceasta face ca indexul ciclului

sa fie incrementat cu 1 la fiecare parcurgere a ciclului . Fara aceasta instructiune ciclul

nu s-ar incheia niciodata .

- 20 -

Page 21: Programare Java

Trebuie mentionat un aspect destul de frecvent intalnit si generator de erori : nu se

pune ; dupa paranteza ) ciclului for :

for (i=0;i<10;i++;

x=x*i;

In exemplul de mai sus ciclul for se incheie dupa primul semn ; , fara a se executa

instructiunea x=x*i ca parte a ciclului . Aceasta eroare poate fi greu de depistat pentru

ca nu apare ca o eroare la compilare – ea este o eroare logica a programatorului .

CICLURI WHILE si DO

Ca si ciclurile for , ciclurile while si do permit executarea unui bloc de cod Java pana

in momentul cand se indeplineste o anumita conditie . Folosirea ciclurilor for , while

sau do este de multe ori o problema doar de stil . Ciclurile while si do sunt identice cu

cele din C , cu exceptia faptului ca testul trebuie sa foloseasca o conditie booleana .

CICLURI WHILE

Ciclul while este folosit pentru a repeta o instructiune atata timp cat o anumita

conditie este adevarata ( true ) .

while (i<10) { x=x*i++;}

In exemplul anterior conditia care insoteste cuvantul cheie while este o expresie

booleana , i<10 . Daca expresia returneaza true ciclul executa corpul sau si apoi

testeaza din nou conditia . Acest proces se repeta pana cand conditia ia valoarea false .

class CopieTablouWhile {

public static void main (String argumente[]) {

int[] tablou1={7,4,8,1,4,1,4};

float[] tablou2=new float[tablou1.length];

System.out.print(“tablou1 : [“);

for (int i=0; i<tablou1.length; i++ ) {

System.out.print(tablou1[i]+” “);

}

System.out.println(“]”);

System.out.print(“tablou2: [ “);

int index=o;

while (index<tablou1.length && tablou1[index]!=1) {

tablou2[index]=(float) tablou1[index];

System.out.print(tablou2[index++]+” “);

}

System.out.println(“]”);

- 21 -

Page 22: Programare Java

}

}

Programul declara doua tablouri – tablou1 este un tablou de intregi , initializat cu

cateva numere . tablou2 este un tablou de numere in virgula mobila , care are aceleasi

dimensiuni cu tablou1 , insa nu are valori initiale .

Programul parcurge apoi iterativ tablou1 afisand valorile din toate pozitiile acestuia ;

in continuare programul verifica valorile din tablou1 si in cazul in care sunt diferite de

1 le transforma in numere reale si le inscrie in tablou2 .

CICLURI DO … WHILE

Acest ciclu este foarte asemanator cu whie – diferenta majora este locul unde se face

testarea conditiei in ciclu . Un ciclu while testeaza conditia inainte de ciclu si astfel

daca avem valoarea false corpul ciclului nu va fi deloc executat . Un ciclu do executa

corpul sau cel putin o data inainte de a testa conditia , deci daca aceasta are valoarea

false la prima testare corpul ciclului se va fi executat deja o data .

do {

x=x*i++;

}

while (i<10);

Corpul ciclului este executat o data inainte de evaluarea conditiei , i<10 .

IESIREA FORTATA DIN CICLURI

In toate tipurile de cicluri acestea isi termina executia atunci cand se indeplineste

conditia testata . Pot fi cazuri in care apare ceva in executia ciclului si dorim sa iesim

mai repede din el . Pentru aceasta pot fi folosite cuvintele cheie break si continue .

Am intalnit deja break in paginile anterioare – break oprea executia instructiunii

switch iar programul continua cu codul urmator instructiunii switch . Cuvantul cheie

break , folosit intr-un ciclu , face acelasi lucru – inceteaza imediat executia ciclului

curent . Daca exista cicluri imbricate in cadrul altor cicluri executia continua cu

urmatoarea iteratie a ciclului din exterior . Astfel , programul continua executia

urmatoarei instructiuni aflata dupa ciclu .

Sa revenim la exemplul ciclului while care copia elementele unui tablou de intregi

intr-un tablou de numere in virgula mobila pana cand se intalnea valoarea 1 . Putem

testa aceasta conditie in cadrul corpului ciclului while , dupa care folosim

instructiunea break pentru a parasi ciclul :

int index=0;

while (index<tablou1.length) {

if (tablou1[index]==1) break;

- 22 -

Page 23: Programare Java

tablou2[index]=(float) tablou1[index++];

}

Cuvantul cheie continue incepe ciclul de la o noua iteratie . Pentru ciclurile do si

while aceasta inseamna ca se incepe din nou cu executia corpului ciclului ; pentru

ciclurile for se evalueaza expresia de incrementare si apoi se executa blocul de

instructiuni . Instructiunea continue este folositoare atunci cand dorim sa tratati intr-

un anume fel elementele intr-un ciclu . Folosind exemplul anterior , de copiere a unui

tablou in altul , putem testa daca valoarea elementului curent este egala cu 1 si sa

folosim continue pentru a reincepe ciclul dupa fiecare 1 intalnit , asa incat tabloul

rezultat sa nu contina niciodata 1 . Trebuie sa fim atenti ca , deoarece sarim peste

unele elemente din primul tablou acum trebuie sa pastram doua valori index pentru

cele doua tablouri :

int index=0;

int index2=0;

while (index++ <=tablou1.length) {

if (tablou1[index]==1)

continue;

tablou2[index2++]=(float)tablou1[index];

}

CICLURI ETICHETATE

Instructiunile break si continue pot avea etichete optionale care sa indice locul de

unde se va continua executia programului . Fara eticheta , break sare in afara celui mai

apropiat ciclu sau la urmatoarea instructiune aflata dupa ciclul . Instructiunea continue

sare la urmatoarea iteratie a ciclului care o contine . Cu ajutorul etichetelor putem

folosi break pentru a sari intr-un punct aflat in afara unui ciclu imbricat sau continue

pentru a sari intr-un ciclu aflat in afara ciclului curent .

Pentru a folosi un ciclu cu etichete se introduce eticheta inainte de partea de inceput a

ciclului , urmata de semnul : . Apoi , dupa numele instructiunii break sau continue

introducem numele etichetei , ca mai jos :

afara:

for (int i=0; i<10; i++ ) {

while (x<50) {

if (i*x++>400) break afara;

// ciclu interior

}

// ciclu exterior

}

In acest exemplu de cod , eticheta afara marcheaza ciclul exterior . In cadrul ciclurilor

for si while , atunci cand este indeplinita o anumita conditie , instructiunea break cu

eticheta are ca rezultat terminarea ambelor bucle . Fara folosirea etichetei afara ,

instructiunea break ar fi terminat executia ciclului interior si ar fi continuat executia

cu cel exterior .

- 23 -

Page 24: Programare Java

Programare Java

Curs – 3

PROGRAMARE ORIENTATA OBIECT – Object Oriented Programming (OOP)

Programarea orientata obiect este un concept remarcabil – chiar daca in realitate nu

este foarte “modern” , el aparand ideatic inca din anii „70! Ideea centrala este destul

de simpla si clara: organizati programele intr-un mod care sa oglindeasca modul cum

sunt organizate obiectele din lumea reala.

In mod normal prezentarea urmatoare ar trebui privita doar ca o recapitulare a

principiilor OOP studiate deja in cadrul limbajului C++.

Un program este privit in general ca o lista de instructiuni care ii spun calculatorului

ce are de facut . Un program este considerat de OOP drept un set de obiecte care

lucreaza impreuna cu scopul de a indeplini o sarcina.

Ca exemplu sa luam un model practic extrem de intalnit in aceste zile - construirea

unui PC din diferite componente separate (placa de baza, placa video, procesor, etc.).

Intern, fiecare dintre aceste componente poate fi extrem de complicata si complexa

dar cel ce asambleaza intregul nu are nevoie sa stie exact detaliile de functionare

interna a fiecarei componente ci doar cateva date foarte concrete :

- se vor potrivi aceste componente la nivel fizic ?

- vor putea lucra impreuna din punct de vedere functional aceste componente ?

Odata cunoscute interactiunile dintre componente realizarea sistemului final va fi

destul de simpla .

Programarea orientata obiect se muleaza perfect pe exemplul anterior ; programul

nostru final se compune din mai multe componente – obiecte care trebuie sa

interactioneze cu succes .

Un obiect este un element independent al unui program , care reprezinta un set de

caracteristici corelate si este proiectat pentru a realiza anumite sarcini . Obiectele mai

sunt numite si instante .

OBIECTE SI CLASE

O clasa este un model ( sablon ) folosit pentru a crea mai multe obiecte cu aceeasi

caracteristici .

Clasele inglobeaza toate caracteristicile unui anumit set de obiecte . Atunci cand

scriem un program intr-un limbaj OOP nu definim obiecte ci clase de obiecte .

Clasele sunt folosite pentru a crea obiecte cu care vom lucra apoi direct in program .

- 24 -

Page 25: Programare Java

Cand scriem un program in Java proiectam si construim un set de clase . Atunci cand

programul ruleaza din aceste clase sunt create obiecte si apoi acestea sunt folosite .

Sarcina programatorului Java este de a crea seturile corecte de clase pentru ca

programul sa se comporte corespunzator .

In practica nici macar nu trebuie pornit de la zero cu constructia claselor . Fiecare

versiune de Java contine un grup de clase care implementeaza caracteristicile de baza

de care au in general nevoie programatorii . Aceste grupe de clase se numesc

biblioteci .

O biblioteca de clase este un grup de clase proiectate pentru a fi folosite impreuna cu

alte programe. Biblioteca de clase Java standard contine mai multe zeci de clase (

depinzand exact de versiunea limbajului ) .

Biblioteca standard Java se ocupa de mai multe sarcini uzuale , cum ar fi functii

matematice , lucru cu text , imagini , sunet, interactiune cu utilizatorul si lucru in

retea . In multe cazuri bibliotecile Java sunt de ajuns pentru un program de nivel

mediu . In acest caz programatorul are ca sarcina doar crearea unei singure clase ,

folosite pentru a crea obiecte pornind de la clasele Java standard si pentru a administra

interactiunile dintre acestea .

Odata cu avansarea in programarea Java se poate crea un set complet nou de clase

care sa aiba definite anumite interactiuni intre ele ; acestea pot fi folosite pentru a se

alcatui eventual o biblioteca proprie de clase care poate fi reutilizata mai tarziu in alte

programe . Aceasta capacitate de reutilizare este unul dintre avantajele majore ale

programarii orientate obiect .

ATRIBUTE SI COMPORTAMENT

Atributele reprezinta parametrii individuali care diferentiaza o clasa de obiecte de o

alta si care determina modul de prezentare , starea si alte calitati ale clasei .

Intr-o clasa atributele sunt definite de variabile . Fiecare obiect poate avea valori

diferite ale variabilelor sale ; acestea se numesc variabile de instanta .

O variabila de instanta este un element de informatie care defineste atributul unui

anumit obiect . Clasa obiectului defineste ce fel de atribut este si fiecare instanta isi

pastreaza propria sa valoare pentru acel atribut . Variabilele de instanta mai sunt

denumite si variabilele obiectului .

Fiecarui atribut al unei clase ii corespunde o singura variabila ; putem schimba

atributul unui obiect modificand aceasta variabila .

Variabilele de instanta pot lua o valoare atunci cand se creeaza un obiect ce ramane

neschimbat pe toata durata lui de existenta sau pot lua diferite valori pe masura ce

obiectul este folosit .

Un alt atribut este folosit pentru descrierea intregii clase de obiecte , nu numai a unui

singur obiect al clasei . Aceste atribute sunt continute in variabile de clasa .

- 25 -

Page 26: Programare Java

O variabila de clasa este un element de informatie care defineste atributul unei intregi

clase . Variabila se aplica insasi clasei si tuturor instantelor ei , deci este stocata o

singura valoare , indiferent cate obiecte ale clasei au fost create .

COMPORTAMENTUL UNEI CLASE DE OBIECTE

Comportamentul este modul in care clasele de obiecte pot face ceva cu ele insele sau

cu alte obiecte . Comportamentul unei clase determina ce obiecte ale clasei isi

modifica atributele , precum si ce fac ele atunci cand alte obiecte le cer sa faca ceva .

Comportamentul unei clase de obiecte este determinat cu ajutorul metodelor .

Metodele sunt grupuri de instructiuni dintr-o clasa de obiecte , care actioneaza asupra

acesteia sau asupra altor clase sau obiecte . Ele sunt folosite pentru a realiza diferite

sarcini , in acelasi fel in care in alte limbaje de programare se folosesc functiile .

Obiectele comunica unele cu altele folosind metodele . O clasa sau un obiect poate

apela metode dintr-o alta clasa sau obiect pentru mai multe motive :

- pentru a raporta o modificare unui alt obiect

- pentru a comunica altui obiect sa modifice ceva in legatura cu el

- pentru a cere unui obiect sa faca ceva

Asa cum exista variabile de instanta si de clasa , exista si metode de instanta si de

clasa . Metodele de instanta , numite si simplu metode , actioneaza asupra unui obiect

al clasei . Daca o metoda efectueaza schimbari doar asupra unui obiect individual ea

trebuie sa fie o metoda de instanta . Metodele de clasa actioneaza asupra clasei insasi .

CREAREA UNEI CLASE

Primul pas este deschiderea editorului de text pe care il folosim pentru a crea

programe java ( fisiere sursa cu extensia .java ) . Cea mai simpla declaratie de clasa

este :

Class ClasaMea {}

In continuare sa urmarim exemplul crearii unei clase Persoana.

class Persoana {

String culoare;

String sex;

boolean flamand; }

Au fost definite mai sus trei variabile de instanta .

Prin adaugarea de metode clasei i se poate defini un comportament . Aceste metode

sunt lucruri pe care le-ar putea face o Persoana – in exemplul nostru vor apare doar

doua metode : una pentr a hrani persoana si alta pentru a-i verifica atributele .

void hranescPersoana() {

- 26 -

Page 27: Programare Java

if (flamand==true) {

System.out.println(“Bun – foame!”);

Flamand=false;

} else

System.out.println(“Nu merci – am mancat!”);

}

In continuare prezentam listingul celei de a doua metode – pentru verificarea

atributelor :

void afisezAtribute() {

System.out.println(“Acesata e o persoana “+sex+” “+culoare);

if (flamand==true) System.out.printl(“Persoana este flamanda”);

else System.out.println(“Persoana e satula”);

}

In acest moment avem o clasa Persoana cu variabile si metode de instanta ce pot fi

folosite pentru a afisa si modifica variabilele .

Pentru a compila programul schimbam directorul curent in directorul care contine

fisierul nostru sursa si folosim comanda :

javac Persoana.java

In cazul in care incercam sa rulam fisierul ( cu comanda : java Persoana ) vom obtine

o eroare . Aceasta apare deoarece interpretorul Java presupune ca programul pe care

incercam sa il executam din linia de comanda este o aplicatie . Atunci cand se executa

o aplicatie punctul ei de lansare este metoda main() . Deoarece clasa noastra nu

poseda o metoda main() avem probleme .

Exista doua metode de a folosi clasa noastra :

1. Cream , separat , un applet sau o aplicatie java care sa foloseasca aceasta clasa

2. adaugam metoda main() in listingul nostru

Pentru a adauga metoda main() se introduc urmatoarele :

public static void main(String argumente[]){ … }

Mai jos avem intregul listing al aplicatiei noastre :

class Persoana {

String culoare;

String sex;

boolean flamand;

void hranescPersoana() {

if (flamand==true) {

System.out.println("Bun - vrea mancare");

flamand=false; }

- 27 -

Page 28: Programare Java

else

System.out.println("Nu multumesc - am mancat deja");

}

void afisezAtribute () {

System.out.println("Aceasta e o persoana de sex " + sex + " " + culoare + " .");

if (flamand==true)

System.out.println("Persoana este flamanda");

else

System.out.println("Persoana este satula");

}

public static void main (String argumente[] ) {

Persoana j=new Persoana();

j.culoare="portocaliu";

j.sex="mascul";

j.flamand=true;

System.out.println("Apelez afisezAtribute ...");

j.afisezAtribute();

System.out.println("___");

System.out.println("Hranesc Persoana ...");

j.hranescJabberwock();

System.out.println("___");

System.out.println("Apelez afisezAtribute ...");

j.afisezAtribute();

System.out.println("---");

System.out.println("Hranesc Persoana ... ");

j.hranescJabberwock();

}

}

ORGANIZAREA CLASELOR SI COMPORTAMENTUL ACESTORA

MOSTENIREA

Mostenirea reprezinta unul dintre cele mai importante concepte ale programarii OOP ,

avand un efect direct asupra modului de proiectare si scriere a claselor noastre Java .

Mostenirea este un mecanism care permite unei clase sa mosteneasca comportamentul

si atributele unei alte clase .

Prin mostenire , o clasa dobandeste imediat tot comportamentul unei clase existente .

Din acest motiv , noua clasa poate fi creata prin simpla specificare a diferentelor fata

de clasa existenta .

Prin mostenire toate clasele sunt aranjate intr-o ierarhie stricta – cele pe care le cream

si cele provenite din biblioteca Java sau din alte biblioteci .

O clasa care mosteneste alta clasa este denumita subclasa iar clasa care isi ofera

mostenirea se numeste superclasa .

- 28 -

Page 29: Programare Java

O clasa poate avea o singura superclasa , insa poate avea un numar nelimitat de

subclase . Subclasele mostenesc toate atributele si comportamentul superclaselor lor .

In varful ierarhiei de clase Java se afla clasa Object – toate clasele mostenesc aceasta

unica superclasa . Object reprezinta cea mai generica clasa din ierarhie , care defineste

comportamentul si atributele mostenite de toate clasele din biblioteca Java . Fiecare

clasa aflata mai jos in ierarhie devine din ce in ce mai adaptata unui scop precis . O

ierarhie de clase defineste conceptele abstracte la varful ierarhiei ; aceste concepte

devin din ce in ce mai concrete odata cu coborarea spre subclase .

In mod normal , cand cream o noua clasa Java dorim ca ea sa prezinte toate

caracteristicile unei clase existente , cu unele modificari ; de exemplu putem dori o

versiune a butonului CommandButton care sa produca un zgomot la folosirea sa .

Pentru a mosteni toate caracteristicile clasei CommandButton fara efort vom defini

noua noastra clasa ca o subclasa a clasei CommandButton . Clasa noastra va mosteni

automat comportamentul si atributele superclasei . Tot ceea ce trebuie sa facem este

sa introducem diferenta fata de superclasa .

Subclasarea reprezinta crearea unei noi clase , care mosteneste o clasa existenta .

Singurul lucru care trebuie facut in subclasa este definirea diferentelor in

comportament si atribute fata de superclasa .

Cand clasa noastra defineste un comportament complet nou si nu este o subclasa

atunci ea mosteneste direct clasa Object . Acest lucru ii permite acesteia sa se

integreze corect in ierarhia claselor Java ; in practica , daca definim o clasa care nu

specifica o superclasa atunci Java presupune automat ca noua clasa mosteneste direct

clasa Object.

Atunci cand cream un nou obiect Java pastreaza urma fiecarei variabile definite

pentru acel obiect si a fiecarei variabile definite pentru fiecare clasa a obiectului . In

acest fel , toate clasele se combina pentru a forma un model al obiectului curent , iar

fiecare obiect isi completeaza informatiile corespunzatoare acestei situatii .

Metodele se comporta in acelasi fel : noile obiecte au acces la toate metodele clasei si

superclaselor de care apartin . Acest lucru este determinat dinamic , atunci cand o

metoda este folosita intr-un program aflat in executie . Daca apelam o metoda a unui

anumit obiect , interpretorul Java verifica mai intai clasa obiectului , pentru a gasi

acea metoda . Daca metoda nu este gasita interpretorul o cauta in superclasa clasei si

asa mai departe pana la gasirea definitiei metodei .

Problema se complica atunci cand o subclasa defineste o metoda cu acelasi nume , tip

de rezultat si argumente care sunt definite si intr-o superclasa . In acest caz se

foloseste definitia metodei care este gasita prima ( incepand din partea de jos a

ierarhiei si mergand in sus ) . Atfel intr-o subclasa putem crea o metoda cu acelasi

nume , tip de rezultat si argumente ca ale metodei din superclasa ; aceasta procedura

se numeste anulare prin suprascriere sau simplu suprascriere .

MOSTENIREA SIMPLA SI MULTIPLA

- 29 -

Page 30: Programare Java

Forma de mostenire folosita in Java este denumita mostenire simpla deoarece fiecare

clasa Java poate avea o singura superclasa .

In alte limbaje de programare – si in C++ - clasele pot avea mai multe superclase ,

mostenind variabile si metode combinate din toate aceste superclase . Aceasta forma

de mostenire este denumita mostenire multipla si ofera mijloace de creare a unor clase

care cuprind aproape orice comportament imaginabil . Totusi , acest lucru complica

mult definitia clasei si a codului necesar pentru producerea acesteia . Java simplifica

acest concept permitand doar mostenirea simpla .

INTERFETE

Mostenirea simpla face ca relatiile intre clase si comportamentul pe care aceste clase

il implementeaza sa devina usor de inteles si de proiectat . Totusi ea poate fi

restrictiva – mai ales atunci cand avem un comportament similar care trebuie duplicat

pe diferite ramuri ale ierarhiei de clase . Java rezolva aceasta problema a

comportamentului partajat prin folosirea interfetelor .

O interfata este o colectie de metode care indica faptul ca o clasa are un anumit

comportament suplimentar fata de ceea ce mosteneste de la superclasele sale .

Tehnic vorbind , o interfata Java nu contine nimic altceva decat definitii de metode

abstracte si constante – fara variabile de instanta sau implementari de metode (

cuvantul cheie folosit pentru a semnala folosirea unei interfete este implements ) .

PACHETE

Pachetele in Java reprezinta o modalitate de a grupa clasele si interfetele inrudite .

Pachetele permit grupurilor de clase sa fie disponibile doar daca este nevoie de ele ,

eliminand potentialele conflicte intre numele claselor din diferite grupuri de clase .

Bibliotecile de clase Java sunt continute intr-un pachet denumit java . Clasele din

pachetul Java sunt disponibile garantat in orice implementare Java si sunt singurele

disponibile in diferite implementari . Pachetul Java contine pachete mai mici care

definesc seturi specifice ale caracteristicilor limbajului Java , cum ar fi caracteristicile

standard , manipularea fisierelor , multimedia , etc . Clasele din alte pachete , ca sun

sau netscape , pot fi disponibile doar in anumite implementari .

In mod prestabilit clasele noastre Java au acces doar la clasele din java.lang (

caracteristicile de baza ale limbajului ) . Pentru a folosi clasele din alte pachete trebuie

sa ne referim explicit la numele pachetului sau sa importam clasele in fisierul nostru

sursa .

Pentru a ne referi la o clasa din cadrul unui pachet trebuie sa introducem toate

pachetele care contin clasa , urmate de numele clasei , elementele fiind separate prin

puncte . De exemplu sa luam clasa Color . Ea este continuta in pachetul awt , care la

randul lui este continut in pachetul java . Pentru a referi clasa Color in program

trebuie folosita notatia java.awt.Color .

CREAREA UNEI SUBCLASE

- 30 -

Page 31: Programare Java

Cea mai uzuala folosire a subclasarii este la crearea de applet-uri . Crearea applet-

urilor este diferita de crearea aplicatiilor ; applet-urile Java ruleaza ca parte a unei

pagini web , deci au reguli specifice privind comportamentul lor . Din cauza acestor

reguli speciale aplicate applet-urilor , crearea unui applet simplu este mai complicata

decat crearea unei aplicatii simple .

Toate applet-urile reprezinta subclase ale clasei Applet ( care face parte din pachetul

java.applet ) . Prin crearea unei subclase a clasei Applet vom mosteni automat

comportamentul si atributele care permit unui program Java sa ruleze ca parte a unei

pagini web .

In continuare vom prezenta un exemplu simplu de applet Java .

Mai intai vom construi definitia clasei :

public class Palindrom extends java.applet.Applet {

….

}

Aceste instructiuni definesc o clasa Palindrom ; singurul lucru nou aparut este textul

extends java.applet.Applet .

Clauza extends reprezinta modul prin care se declara o clasa ca fiind o subclasa a

alteia . Clasa Palindrom este o subclasa a clasei Applet , care face parte din pachetul

java.applet. Pentru a indica in program faptul ca intre cele doua clase exista o relatie

se foloseste clauza extends .

Cuvantul cheie public indica faptul ca aceasta clasa a noastra este accesibila altor

clase care ar putea avea nevoie sa o foloseasca . In mod normal , singurul motiv

pentru care am avea nevoie sa definim o clasa drept publica este atunci cand dorim ca

ea sa fie accesata de catre alte clase din programul nostru . Totusi , in cazul applet-

urilor trebuie sa folosim totdeauna declaratia public .

Sa adaugam acum o noua instructiune in program :

Font f=new Font(“TimesRoman”,Font.BOLD,36);

Aceasta instructiune realizeaza doua lucruri :

- se creaza un obiect de tip Font , numit f . Font , componenta a pachetului

java.awt , este folosit pentru a reprezenta un font pe ecran . Clasa este folosita

pentru a afisa un font si un stil diferite de cele folosite implicit de un applet .

- obiectului Font i se atribuie o valoare de font de 36 de puncte , stil

TimesRoman , cu litere aldine . Instructiunea new creaza un nou obiect de tip

Font avand valorile specificate in paranteze si care este atribuit variabilei f .

Prin crearea unei variabile de instanta care sa-l contina , am facut obiectul Font

disponibil tuturor metodelor din clasa noastra . Urmatorul pas in proiectul nostru este

de a crea o metoda care sa-l foloseasca .

- 31 -

Page 32: Programare Java

Atunci cand scriem applet-uri , exista mai multe metode definite in superclasa Applet

, care , de obicei , sunt anulate prin suprascriere . Printre acestea exista metode care

configureaza applet-ul inainte de a fi lansat in executie , care lanseaza applet-ul , care

raspund la evenimentele mouse-ului sau care elibereaza memoria cand applet-ul isi

inceteaza executia .

Una dintre aceste metode este paint() , care se ocupa de orice se intampla cand applet-

ul este afisat pe pagina web . Metoda paint() mostenita de clasa Palindrom nu face

nimic – este o metoda goala . Prin suprascrierea metodei paint() vom indica ce anume

dorim sa fie desenat in fereastra applet-ului , ori de cate ori este nevoie sa se afiseze

ceva , atunci cand programul ruleaza .

Sa adaugam la clasa noastra urmatoarele instructiuni :

public void paint(Graphics ecran) {

ecran.setFont(f);

ecran.setColor(Color.red);

ecran.drawString(“Go hang a salami , I‟m a lasagna hog”,5,40);

}

Metoda paint() este declarata public , ca si applet-ul ; acest lucru apare deoarece

metoda pe care o suprascrie este si ea publica . O metoda publica apartinand unei

superclase nu poate fi suprascrisa decat de o metoda publica , altfel apar erori la

compilare .

Metoda paint() preia un singur argument : o instanta a clasei Graphics , denumita la

noi ecran . Clasa Graphics se ocupa cu reprezentarea fonturilor , culorilor si desenarea

liniilor si altor forme .

In metoda paint() se realizeaza trei lucruri :

- am indicat obiectului Graphics faptul ca fontul pe care vrem sa-l folosim este

cel continut in variabila de instanta f

- am indicat obiectului Graphics faptul ca, culoarea pe care dorim sa o folosim

pentru text si alte operatii de desenare este o instanta a clasei Color pentru

culoarea rosu ( red ) .

- in final am scris pe ecran un text la coordonatele x,y egale cu 5 si 40 .

La acest moment applet-ul nostru arata astfel :

public class Palindrom extends java.applet.Applet {

Font f=new Font("TimesRoman",Font.BOLD,36);

public void paint(Graphics monitor) {

monitor.setFont(f);

monitor.setColor(Color.red);

monitor.drawString("Go hang a salami , I'm a lasagna hog",5,40);

}

}

- 32 -

Page 33: Programare Java

In cazul in care incercam sa compilam acest fisier sursa vom obtine o serie de erori

de genul : “Class not found”

Aceste erori apar deoarece clasele Graphics , Font si Color apartin pachetului java.awt

, care nu este disponibil implicit . Am referit clasa Applet din prima linie a sursei prin

numele sau complet – incluzand si numele pachetului din care face parte . In restul

programului am referit insa celelalte clase fara a folosi numele pachetului din care

acestea fac parte .

Exista doua metode pentru a rezolva problema :

- referim toate clasele externe prin numele lor complet , cum ar fi

java.awt.Graphics

- folosim instructiunea import la inceputul programului pentru a face disponibile

unul sau mai multe pachete si clase .

Pentru o scriere mai usoara si mai rapida a codului sursa se foloseste de obicei a doua

varianta , fapt tradus in programul nostru prin inserarea liniilor :

import java.awt.Graphics;

import java.awt.Color;

import java.awt.Font;

Pentru o si mai mare usurinta putem folosi simbolul “*” in locul unui anumit nume de

clasa . Putem astfel folosi instructiunea :

import java.awt.*;

Deoarece fisierul sursa contine o clasa publica , Palindrom , numele fisierului trebuie

sa fie identic cu numele clasei publice – cu folosirea corecta a majusculelor si

minusculelor .

Pentru a putea vedea ce am realizat trebuie sa cream o pagina web care sa foloseasca

applet-ul nostru .

Vom crea o pagina web cu urmatorul continut :

<applet code=”Palindrom.class” width=600 height=100>

</applet>

- atributul CODE indica numele clasei care contine applet-ul

- atributele WIDTH si HEIGHT determina cat de mare va fi fereastra applet-

ului in cadrul paginii web , exprimat in pixeli .

In lipsa unui browser putem folosi pentru a vizualiza pagina noastra utilitarul

appletviewer din pachetul JDK , cu sintaxa :

appletviewer Palindrom.html

Acest utilitar , spre deosebire de un browser , va afisa doar applet-urile incluse in

pagina web , neafisand nimic altceva continut eventual in pagina .

- 33 -

Page 34: Programare Java

OBIECTE

CREAREA DE NOI OBIECTE

Atunci cand scriem un program Java de fapt definim un set de clase ; clasele sunt

modele dupa care se genereaza obiecte .

In cele mai multe situatii vom folosi clasele pentru a crea instante si vom lucra cu

aceste instante .

In cursurile anterioare am intalnit o instanta a clasei String creata prin folosirea unui

literal sir ( o serie de caractere incadrate intre ghilimele ) .

Celelalte clase Java nu au aceasta posibilitate de creare a unui nou obiect . Crearea de

noi instante ale acestora se face explicit cu operatorul new .

Pentru a crea un nou obiect folosim operatorul new impreuna cu numele clasei dupa

modelul careia dorim sa cream o instanta , urmata de paranteze :

String numeEchipa=new String();

Jabberwock j=new Jabberwock();

Parantezele sunt foarte importante ; in cazul in care acestea sunt goale se creaza cel

mai simplu obiect – in cazul in care exista argumente intre ele acestea determina

valorile initiale ale variabilelor de instanta sau ale altor calitati initiale ale obiectului

respectiv :

Point pt=new Point(0,0);

Numarul si tipul argumentelor pe care le folosim intre paranteze impreuna cu

operatorul new sunt definite de clasa folosind o metoda speciala denumita constructor

. Daca incercam sa cream o noua instanta a clasei folosind un numar gresit de

argumente sau un tip eronat al acestora vom obtine erori la compilarea programului .

La folosirea operatorului new se intampla mai multe lucruri : se creaza o noua instanta

a clasei date , se aloca memorie pentru aceasta si se apeleaza o metoda speciala a

clasei . Aceasta metoda speciala se numeste constructor .

Constructorii reprezinta metode speciale pentru crearea si initializarea noilor instante

ale claselor . Constructorii initializeaza noul obiect si variabilele sale , creaza orice

alte obiecte de care are nevoie obiectul creat si realizeaza orice alte operatii de care

obiectul are nevoie la initializarea sa .

Intr-o clasa pot exista mai multe definitii de constructori , fiecare avand un numar

diferit de argumente sau tipuri . Atunci cand folosim operatorul new putem specifica

diferite argumente in lista de argumente si va fi apelat constructorul corespunzator

pentru acele argumente . La crearea unei clase putem defini oricati constructori avem

nevoie pentru implementarea comportamentului clasei .

- 34 -

Page 35: Programare Java

GESTIONAREA MEMORIEI

Gestionarea memoriei in Java se face dinamic si automat . Atunci cand cream un

obiect nou Java aloca automat o zona de memorie de dimensiunea corespunzatoare

obiectului . Nu trebuie sa alocam explicit memorie pentru obiecte .

Deoarece gestionarea memoriei se face automat nu este nevoie sa dezalocam memoria

ocupata de obiect atunci cand am terminat de lucrat cu acesta . Atunci cand am

terminat lucrul cu obiectul acesta nu mai poseda nici o referinta activa catre el ( nu va

mai fi atribuit nici unei variabile pe care o folosim sau nu va mai fi stocat in vreun

tablou ) . Java poseda un “garbage collector” care cauta obiectele nefolosite si

recupereaza memoria ocupata de acestea . Nu trebuie sa eliberam explicit acea zona

de memorie .

ACCESAREA SI STABILIREA VARIABILELOR DE CLASA SI DE INSTANTA

Variabilele de clasa si de instanta se comporta in acelasi fel ca si variabilele locale .

Trebuie doar sa ne referim la ele intr-o modalitate usor diferita .

OBTINEREA VALORILOR

Pentru a obtine valoarea unei variabile de instanta vom folosi notatia cu punct . In

aceasta notatie variabila de instanta sau de clasa este formata din doua parti : obiectul

, in partea stanga a punctului si variabila , in partea dreapta .

De exemplu , daca avem un obiect atribuit variabilei clientulMeu si acel obiect poseda

o variabila denumita totalFactura atunci ne vom referi la aceasta variabila astfel :

clientulMeu.totalFactura;

Aceasta forma de accesare a variabilelor este o expresie ( deoarece intoarce o valoare

) in care de ambele parti ale punctului se afla tot expresii . Acest lucru inseamna ca

putem insera mai multe variabile de instanta . Daca variabila totalFactura refera ea

insasi un obiect care poseda propria variabila de instanta numita rezervat , putem sa ne

referim la aceasta astfel :

clientulMeu.totalFactura.rezervat;

Expresiile cu punct sunt evaluate de la stanga spre dreapta , asa incat se va incepe cu

variabila din clientulMeu , totalFactura , care refera un alt obiect cu variabila rezervat

. In final vom obtine valoarea variabilei rezervat .

MODIFICAREA VALORILOR

Atribuirea unei valori acelei variabile se face pur si simplu prin utilizarea operatorului

de atribuire :

- 35 -

Page 36: Programare Java

clientulMeu.totalFactura.rezervat=true;

In continuare avem un exemplu simplu de accesare a variabilelor prin notatia cu punct

:

import java.awt.Point;

class DefinirePuncte {

public static void main(String argumente[]) {

Point pozitie=new Point(4,13);

System.out.println(“Pozitia de inceput:”);

System.out.println(“X egal “+pozitie.x);

System.out.println(“Y egal “+pozitie.y);

System.out.println(“\nSe muta in (7,6)”);

pozitie.x=7;

pozitie.y=6;

System.out.println(“Pozitia finala:”);

System.out.println(“X egal “+pozitie.x);

System.out.println(“Y egal “+pozitie.y);

}

}

VARIABILE DE CLASA

Dupa cum am vazut o variabila de clasa este definita si memorata chiar in clasa

respectiva . Valorile variabilelor de clasa se aplica clasei si tuturor instantelor sale .

In cazul variabilelor de instanta fiecare noua instanta primea o copie a variabilelor de

instanta definite in clasa . Fiecare instanta poate modifica apoi valorile acestor

variabile fara a afecta alte instante . In cazul variabilelor de clasa exista o singura

copie a acesteia . Modificarea valorii sale este vizibila in toate instantele clasei .

Variabilele de clasa se definesc prin inserarea cuvantului cheie static inaintea numelui

variabilei . De exemplu , sa luam urmatoarea definitie de clasa :

class MembruFamilie {

static String numeFamilie=”Popescu”;

String prenume;

int varsta;

}

Instantele clasei noastre poseda propriile valori pentru prenume si varsta insa variabila

de clasa numeFamilie are o valoare comuna pentru toti membrii familiei . Daca se

modifica valoarea acestei variabile toate instantele clasei MembruFamilie vor fi

afectate .

Pentru accesarea acestor variabile de clasa se foloseste aceeasi notatie cu punct .

Pentru a obtine sau modifica valoarea unei variabile de clasa in partea stanga a

punctului putem folosi atat numele instantei cat si al clasei . Ambele linii urmatoare

vor afisa aceeasi valoare :

- 36 -

Page 37: Programare Java

MembruFamilie tata=new MembruFamilie();

System.out.println(“Numele “ “+tata.numeFamilie);

System.out.println(“Numele “ “+MembruFamilie.numeFamilie);

In practica este recomandabil sa folosim numele de clasa in stanga punctului cand ne

referim la o variabila de clasa . Astfel codul va fi mai usor de citit si depanat .

APELAREA METODELOR

Apelarea unei metode a unui obiect este asemanatoare referirii variabilelor de instanta

: folosim notatia cu punct . Obiectul a carui metoda o apelam este in stanga punctului

iar numele metodei si ale argumentelor sale in dreapta :

clientulMeu.adaugInFactura(codProdus,pret);

Mentionez din nou ca toate metodele sunt obligatoriu urmate de paranteze – cu sau

fara argumente .

Daca metoda apelata returneaza un obiect care poseda la randul lui metode putem

imbrica metodele la fel ca la variabile . Urmatorul exemplu apeleaza metoda

discutaCuDirectorul() , care este definita in obiectul returnat de metoda

anuleazaToateComenzile() , care a fost definita in obiectul clientulMeu :

clientulMeu.anuleazaToateComenzile().discutaCuDirectorul();

System.out.println() – metoda cea mai folosita pana acum este un exemplu de

imbricare a variabilelor si metodelor . Clasa System , parte a pachetului java.lang ,

descrie comportamentul specific sistemului pe care ruleaza Java .

System.out este o variabila de clasa care contine o instanta a clasei PrintStream .

Acest obiect PrintStream reprezinta iesirea standard a sistemului , care in mod normal

este ecranul . Obiectele PrintStream poseda o metoda println() care trimite un sir catre

fluxul de iesire .

In exemplul de mai jos vom putea vedea cele mai utilizate metode definite in clasa

String :

class VerificareSir {

public static void main(String argumente[]) {

String str=”In viata mea urmatoare , voi crede in reincarnare”;

System.out.println(“Sirul este: ”+str);

System.out.println(“Lungimea sirului este :”+str.length());

System.out.println(“Caracterul din pozitia 7 : “+str.charAt(7));

System.out.println(“Subsirul de la 9 la 11 : ”+str.substring(9,11));

System.out.println(“Indexul caracterului u: “+str.indexOf(„u‟));

System.out.println(“Indexul inceputului “+”subsirului \”voi\” : “+str.indexOf(“voi”));

System.out.println(“Sirul scris cu litere mari : “+str.toUpperCase());

}

- 37 -

Page 38: Programare Java

}

METODE DE CLASA

Metodele de clasa , ca si variabilele de clasa , se aplica unei clase in intregul sau si nu

instantelor sale . Metodele de clasa sunt utilizate de obicei drept metode de uz general

, care nu pot opera direct asupra unei instante a clasei , dar se potrivesc conceptual in

cadrul clasei . De exemplu , clasa String contine o metoda numita valueOf() , care

poate prelua mai multe tipuri de argumente ( intregi , booleeni , alte obiecte s.a.m.d. )

. Metoda valueOf() intoarce o noua instanta a clasei String , care contine valoarea

argumentului sub forma de sir . Aceasta metoda nu opereaza direct asupra unei

instante String insa obtinerea unui sir dintr-un alt tip de data este in mod clar o

operatie apartinand clasei String si are deci sens sa fie definita in clasa String .

Metodele de clase pot fi de asemenea folositoare pentru adunarea unor metode

generale intr-un singur loc ( o clasa ). De exemplu, clasa Math , definita in java.lang ,

contine un set larg de operatii matematice definite ca metode de clase – nu exista

instante ale clasei Math si totusi putem folosi metodele sale impreuna cu argumente

booleene sau numerice . De exemplu sa luam metoda de clasa Math.max :

Int pretMaxim=Math.max(primulPret,alDoileaPret);

Ca si in cazul variabilelor de clasa accesarea metodelor de clasa se poate face folosind

in stanga punctului fie numele clasei fie numele de instanta .

Exemplul de mai jos va produce acelasi rezultat in ultimele sale doua linii :

String s,s2;

s=”articol”;

s2=s.valueOf(5);

s2=String.valueOf(5);

- 38 -

Page 39: Programare Java

Programare Java

Curs – 4

REFERINTE LA OBIECTE

Pe masura ce lucram cu obiecte un lucru important de inteles il reprezinta folosirea

referintelor .

O referinta este un tip de pointer folosit pentru a indica valoarea unui obiect .

Atunci cand atribuim un obiect unei variabile sau trasmitem un obiect ca argument

pentru o metoda nu folosim de fapt obiecte . Nu folositi nici macar copii ale obiectului

. De fapt folosim referinte catre acele obiecte .

Import java.awt.Point;

class TestReferinte {

public static void main(String arg[]) {

Point pt1,pt2;

pt1=new Point(100,100);

pt2=pt1;

pt1.x=200;

pt1.y=200;

System.out.println(“Punct 1: “+pt1.x+”, “+pt1.y);

System.out.println(“Punct 2: “+pt2.x+”, “+pt2.y);

}

}

Desi la o prima vedere variabilele pt1 si pt2 ar trebui sa aiba valori diferite totusi nu

este asa . Variabilele x si y pentru pt2 au fost si ele schimbate chiar daca in program

nu se vede nimic explicit . Motivul este ca in linia 6 s-a creat o referinta de la pt2 la

pt1 , in loc sa se creeze pt2 ca un nou obiect , copiat din pt1.

pt2 este o referinta la acelasi obiect ca si pt1 . Oricare dintre variabile poate fi folosita

pentru a referi obiectul sau pentru a-I modifica variabilele .

Daca doream ca pt1 si pt2 sa se refere obiecte separate , trebuiau folosite instructiuni

new Point() separate in liniile 5 si 6 :

pt1=new Point(100,100);

pt2=new Point(100,100);

Folosirea referintelor in Java devine si mai importanta atunci cand transmitem

argumentele metodelor .

CASTINGUL SI CONVERSIA OBIECTELOR SI TIPURILOR PRIMITIVE

- 39 -

Page 40: Programare Java

Atunci cand transmitem argumente metodelor sau cand folosim variabile in expresii ,

trebuie sa folosim variabile cu tipuri de date corespunzatoare . Daca metoda creata

necesita un int , compilatorul Java raspunde cu eroare daca incercam sa transmitem o

valoare float . La fel , daca incercam sa setam o variabila cu valoarea alteia , ele

trebuie sa fie de acelasi tip .

Uneori obtinem intr-un program Java o valoare care nu este de tipul necesar . Poate fi

dintr-o alta clasa sau dintr-un tip de data necorespunzator – cum ar fi float cand avem

nevoie de un int .

Pentru a inlatura acest neajuns trebuie sa folosim casting-ul .

Casting-ul reprezinta procesul de generare a unei valori de un alt tip decat sursa .

Atunci cand efectuam un cast valoarea variabilei nu se schimba ; de fapt se creaza o

noua variabila de tipul dorit .

Chiar daca conceptul de casting este relativ simplu , folosirea sa este destul de

complicata de faptul ca Java poseda atat tipuri primitive ( int , float , boolean , etc )

cat si tipuri obiect ( String , ZipFile , Point , etc. ) . Exista trei tipuri de cast si de

conversie despre care vom vorbi :

- castingul intre tipuri primitive ( int – float , float-double , etc. )

- castingul intre o instanta a unei clase si o instanta a altei clase

- conversia tipurilor primitive in obiecte si apoi extragerea valorilor primitive

din aceste obiecte .

CASTINGUL INTRE TIPURI PRIMITIVE

Cea mai des intalnita situatie este in cazul tipurilor numerice . Exista un tip de date

primitiv care nu poate fi niciodata folosit pentru cast ; variabilele booleene sunt fie

true fie false si nu pot fi folosite intr-o operatie de cast .

In multe operatii de cast intre tipuri primitive destinatia poate stoca valori mai mari

decat sursa , astfel incat valoarea sa fie convertita cu usurinta . Un exemplu ar fi

castingul unui byte la int . Deoarece byte-ul stocheaza informatii intre -128 si 127 iar

un int informatii intre -2.1 milioane si 2.1 milioane este loc mai mult decat suficient

pentru a face cast de la byte la int .

De multe ori putem folosi automat un byte sau un char drept un int ; putem folosi un

int drept un long , un int drept un float sau orice drept un double . In majoritatea

cazurilor , deoarece tipul de dimensiuni mai mari ofera mai multa precizie decat cel cu

dimensiuni mai mici , nu apare nici o pierdere de informatie . Exceptia apare atunci

cand facem un cast de la intregi la valori in virgula mobila – castingul unui int sau al

unui long intr-un float sau al unui long intr-un double poate duce la pierderi ale

preciziei .

Trebuie sa folosim un cast explicit pentru a converti o valoare mai mare intr-una mai

mica , deoarece conversia valorii poate duce la o pierdere de precizie . Cast-urile

explicite au sintaza :

(numetip)valoare

- 40 -

Page 41: Programare Java

numetip este numele tipului de data catre care facem conversia ; valoare reprezinta o

expresie care are ca rezultat valoarea tipului sursa .

Deoarece precedenta castingului este mai mare decat a operatiilor aritmetice trebuie sa

folosim paranteze – altfel putand apare probleme .

CASTINGUL OBIECTELOR

Instantelor claselor li se poate aplica operatia de cast catre instante ale altor clase , cu

o restrictie ; clasele sursa si destinatie trebuie sa fie inrudite prin mostenire . O clasa

trebuie sa fie subclasa a alteia .

Asemanator conversiei unei valori primitive catre un tip de dimensiuni mai mari ,

unele obiecte nu au nevoie de cast explicit . In particular , deoarece subclasele contin

toate informatiile superclasei lor putem folosi o instanta a unei subclase oriunde se

asteapta folosirea unei superclase .

De exemplu , sa luam o metoda care preia doua argumente : unul de tip Object si altul

de tip Window . Putem transmite o instanta a oricarei clase drept argument Object (

pentru ca toate clasele Java sunt subclase ale clasei Object ) ; pentru argumentul

Window putem transmite si instante ale subclaselor sale ( cum ar fi Dialog ,

FileDialog sau Frame ) .

Reciproca este si ea adevarata ; putem folosi o superclasa acolo unde se asteapta o

subclasa . Exista totusi in acest caz o problema – deoarece subclasele au un

comportament mai complex decat superclasele lor exista o pierdere de precizie . Acele

obiecte superclasa s-ar putea sa nu posede intregul comportament necesar pentru a

putea actiona in locul obiectului subclasa . De exemplu , daca avem o operatie care

apeleaza metode din obiectele apartinand clasei Integer , folosirea unui obiect din

clasa Number ( generica ) nu va dispune de multe metode dintre cele definite in clasa

Integer .

Pentru a folosi obiecte superclasa acolo unde se asteapta obiecte subclasa , trebuie sa

facem cast explicit . Nu vom pierde nici o informatie prin cast , dar vom castiga toate

metodele si variabilele pe care le defineste subclasa . Pentru a face cast pentru un

obiect dintr-o alta clasa folosim aceeasi operatie ca si in cazul tipurilor primitive :

(numeclasa)obiect

numeclasa este numele clasei destinatie , iar obiect este o referinta catre obiectul sursa

. Retinem ca operatia de cast creaza o referinta catre vechiul obiect , de tip numeclasa

; vechiul obiect continua sa existe ca si inainte .

In exemplul de mai jos putem vedea un cast de la o instanta a clasei VicePresedinte

catre o instanta a clasei Angajat ; VicePresedinte este o subclasa a clasei Angajat , cu

informatii suplimentare care definesc faptul ca VicePresedinte are anumite drepturi

suplimentare :

Angajat ang=new Angajat();

VicePresedinte vip=new VicePresedinte();

- 41 -

Page 42: Programare Java

ang=vip; //nu este nevoie de cast de jos in sus

vip=(VicePresedinte)ang; // e nevoie de cast explicit

In afara de castingul obiectelor catre clase putem de asemenea face castingul

obiectelor catre interfete – insa numai daca clasa obiectului respectiv sau una dintre

superclasele sale implementeaza de fapt interfata . Castingul unui obiect catre o

interfata inseamna ca putem apela una dintre metodele interfetei , chiar daca clasa

obiectului nu implementeaza de fapt interfata .

CONVERSIA TIPURILOR PRIMITIVE IN OBIECTE SI INVERS

Unul dintre lucrurile pe care nu le putem face in nici un caz este un cast intre un

obiect si un tip de date primitiv sau invers . Tipurile primitive si obiectele sunt lucruri

foarte diferite in Java si nu putem face cast automat intre cele doua sau sa le folosim

unul in locul celuilalt .

Ca alternativa , pachetul java.lang contine clase care corespund fiecarui tip de date

primitive : Integer , Float , Boolean s.a.m.d . Remarcam faptul ca numele acestor clase

incep cu litera mare . Java trateaza foarte diferit tipurile de date si versiunile clasa ale

acestora ; programele nu se vor compila cu succes daca se folosesc una in locul

celeilalte .

Folosind metodele de clasa definite in aceste clase putem crea un obiect pentru fiecare

dintre tipurile primitive , folosind operatorul new . Urmatoarea instructiune creaza o

instanta a clasei Integer cu valoarea 4455 :

Integer numar=new Integer(4455);

Odata creat un obiect in acest fel putem sa il folosim ca pe orice alt obiect . Atunci

cand dorim sa folosim valoarea din nou ca primitv exista metode speciale , ca mai jos

:

Int numarNou=numar.intValou(); // returneaza 4455

O conversie de care este adesea nevoie in programe este conversia unui sir intr-un tip

numeric , cum ar fi un intreg . Acest lucru se poate face cu metoda parseInt a clasei

Integer , ca in exemplul de mai jos :

String nume=”12000”;

Int numar=Integer.parseInt(nume);

COMPARAREA VALORILOR OBIECTELOR SI ALE CLASELOR

In afara de casting exista si alte operatii ce pot fi aplicate asupra obiectelor :

- compararea obiectelor

- gasirea clasei de care apartine un obiect

- testarea daca un obiect reprezinta o instanta a unei clase date

- 42 -

Page 43: Programare Java

COMPARAREA OBIECTELOR

Aceasta operatie se realizeaza in Java cu ajutorul operatorilor “== “ si “!=” . Atunci

cand sunt folositi cu obiecte acesti operatori nu realizeaza ceea ce ne-am astepta . In

loc de a verifica daca unul dintre obiecte are aceeasi valoare cu celalalt obiect ele

determina daca obiectele sunt de fapt acelasi obiect .

Pentru a compara instantele unei clase si a obtine rezultate folositoare trebuie

implementate metode speciale in cadrul clasei si apoi apelate aceste metode .

Un bun exemplu este clasa String . Este posibil sa avem doua obiecte String diferite

care sa contina aceeasi valoare . Daca folosim operatorul “==” pentru a compara

aceste obiecte ele vor fi considerate diferite . Pentru a vedea daca doua obiecte String

au valori identice se foloseste o metoda a clasei , numita equals() . Metoda testeaza

fiecare caracter din sir si returneaza valoarea true daca cele doua siruri contin aceleasi

valori .

Exemplul de mai jos ilustreaza cele comentate mai sus :

class TestEgalitate {

public static void main(String arg[]) {

String str1,str2;

str1=”Test de egalitate intre siruri.”);

str2=str1;

System.out.println(“Sir1 : “+str1);

System.out.println(“Sir2 : “+str2);

System.out.println(“Acelasi obiect ? “+(str1==str2));

Str2=new String(str1);

System.out.println(“Sir1 : “+str1);

System.out.println(“Sir2 : “+str2);

System.out.println(“Acelasi obiect ? “+(str1==str2));

System.out.println(“Aceeasi valoare ? “+str1.equals(str2));

}

}

Literalele sir sunt optimizate in Java – daca am crea un sir folosind un literal si apoi

folosim un literal cu aceleasi caractere , Java stie suficient pentru a ne oferi acelasi

obiect String . Ambele siruri reprezinta acelasi obiect – trebuie sa actionam diferit

pentru a crea doua obiecte separate .

DETERMINAREA CLASEI UNUI OBIECT

In exemplul de mai jos este exemplificata aflarea clasei pentru un obiect atribuit

variabilei obj :

String nume=obj.getClass().getName();

- 43 -

Page 44: Programare Java

Metoda getClass()este definita in clasa Object , deci va fi disponibila pentru toate

obiectele . Rezultatul metodei este un obiect Class ( unde Class este el insusi o clasa )

, care poseda o metoda numita getName() care returneaza un sir reprezentand numele

clasei .

Un alt test care poate fi folositor este operatorul instanceof . Acesta are doi operanzi :

un obiect in stanga si un nume de clasa in dreapta . Expresia intoarce true sau false in

functie daca obiectul este instanta a clasei numite sau a oricarei subclase a ei :

“peste_sabie” instanceof String // va returna valoarea true

Point pt=new Point(10,10);

pt instanceof String // returneaza valoarea false

Operatorul instanceof poate fi folosit si pentru interfete ; daca un obiect

implementeaza o interfata , operatorul instanceof cu numele interfetei respective in

partea dreapta va intoarce valoarea true .

INSPECTAREA CLASELOR SI A METODELOR PRIN REFLEXIE

Una dintre imbunatatirile aduse limbajului Java dupa versiunea 1.0 a fost introducerea

reflexiei , cunoscuta si sub numele de introspectie . Sub orice nume s-ar folosi ,

reflexia permite unei clase Java – cum sunt toate programele scrise pana acum – sa

afle detalii despre orice alta clasa .

Prin reflexie un program Java poate incarca o clasa despre care nu stie nimic , sa afle

despre variabilele , metodele si constructorii clasei si apoi sa lucreze cu ele .

Listingul de mai jos prezinta o aplicatie Java care creaza un obiect de tip Random si

apoi foloseste reflexia pentru a afisa toate metodele publice care fac parte din clasa :

import java.lang.reflect.*;

import java.util.Random;

class AflaMetode {

public staic void main(String[] arg) {

Random rd=new Random();

Class numeClasa=rd.getClass();

Method[] metode=numeClasa.getMethods();

for (int i=0;i<metode.length;i++) {

System.out.println(“Metoda : “+metode[i]);

}

}

}

Folosind reflexia , aplicatia AflaMetode poate afla informatii despre fiecare metoda a

clasei Random si despre toate metodele pe care le-a mostenit de la superclasa Random

.

Aplicatia AflaMetode poate functiona pentru orice clasa de obiecte .

Reflexia este folosita de obicei de utilitare ca browserele de clasa sau depanatoarele ,

ca o modalitate de a afla mai multe despre clasa de obiecte analizata sau depanata .

- 44 -

Page 45: Programare Java

Este de asemenea folosita de JavaBeans , unde posibilitatea unui obiect de a interoga

un alt obiect asupra a ceea ce poate sa faca ( urmata de o cerere de a efectua ceva )

este folositoare in crearea aplicatiilor mai mari .

Pachetul java.lang.reflect contine urmatoarele clase :

- Field – gestioneaza si afla informatii despre variabilele de instanta si de clasa

- Method – gestioneaza metodele de clasa si de instanta

- Constructor – gestioneaza metodele speciale de creare a noilor instante de

clasa

- Array – gestioneaza tablouri

- Modifier – decodifica informatii de modificare despre clase , variabile si

metode .

In plus exista un numar de noi metode disponibile intr-o clasa de obiecte numita Class

, care ajuta la conectarea diferitelor clase de reflexie .

Reflexia reprezinta un element avansat de programare pe care este posibil sa nu il

folosim in programe prea des dar care devine foarte importanta atunci cand se

lucreaza cu JavaBeans si alte elemente de programare Java avansate .

CREAREA CLASELOR

DEFINIREA CLASELOR

Ca o scurta recapitulare prezentam mai jos o definitie de clasa :

class Stiri {

// corpul clasei

}

In mod prestabilit toate clasele mostenesc clasa Object , care este superclasa tuturor

claselor din ierarhia Java .

Daca respectiva noastra clasa este o subclasa folosim cuvantul cheie extends pentru a

indica superclasa noii clase :

class StiriSportive extends Stiri {

// corpul clasei

}

CREAREA VARIABILELOR DE CLASA SI DE INSTANTA

Atunci cand cream o clasa care mosteneste o superclasa trebuie precizat

comportamentul noii clase , care o face sa difere de superclasa sa . Acest

comportament este definit prin specificarea variabilelor si metodelor noii clase .

DEFINIREA VARIABILELOR DE INSTANTA

- 45 -

Page 46: Programare Java

Variabilele de instanta sunt declarate si definite cam la fel cu variabilele locale .

Principala diferenta consta in localizarea acestora in cadrul clasei , in afara metodelor

, ca in exemplul de mai jos :

class Jabberwock extends Reptile {

String culoare;

String sex;

boolean flamand;

int varsta;

}

CONSTANTE

Variabilele sunt folositoare atunci cand avem nevoie sa pastram informatii ce vor fi

modificate pe parcursul rularii programului . Daca valoarea nu se schimba niciodata

pe parcursul executiei programului putem folosi un tip special de variabila , numit

constanta .

O constanta , denumita si variabila constanta , este o variabila a carei valoare nu se

modifica niciodata .

Constantele se folosesc pentru definirea valorilor comune pentru toate metodele unui

obiect , cu alte cuvinte , pentru denumirea unor valori ce nu se vor schimba in cadrul

obiectului . In Java putem crea constante pentru toate tipurile de variabile : de instanta

, de clasa sau locale .

Pentru a declara o constanta folosim cuvantul cheie final inainte de declararea

variabilei si atribuim valoarea initiala pentru variabila respectiva , ca in exemplele de

mai jos :

final float pi=3.1415;

final booleandebug=false;

final int telefon=8675309;

Constantele pot fi folositoare pentru denumirea diferitelor stari ale unui obiect sau

pentru testarea acestor stari . Folosirea constantelor usureaza de cele mai multe ori

intelegerea programului .

VARIABILE DE CLASA

Acestea se aplica unei clase in intregul sau ( dupa cum am vazut si in cursurile

precedente ) , nefiind stocate individual in obiectele ( instantele ) clasei .

Variabilele de clasa folosesc la comunicarea intre diferite obiecte ale aceleiasi clase

sau pentru pastrarea unor informatii comune la nivelul intregii clase .

Pentru a declara o variabila de clasa se foloseste cuvantul cheie static , ca mai jos :

static int suma;

- 46 -

Page 47: Programare Java

static final int maxObiecte=10;

CREAREA METODELOR

Metodele definesc comportamentul unui obiect – actiunile efectuate la crearea

obiectului sau pe parcursul duratei sale de viata .

DEFINIREA METODELOR

Aceasta cuprinde patru parti :

- numele metodei

- tipul obiectului sau tipul de date primitiv returnat de metoda

- o lista de parametri

- corpul metodei

Primele trei parti ale unei definitii de metoda formeaza ceea ce se numeste semnatura

metodei .

In definirea metodei mai exista si doua alte parti optionale : un modificator ( cuvintele

cheie public sau private ) si cuvantul cheie throws ( care indica exceptiile pe care le

poate semnala metoda ) .

In alte limbaje numele metodei – numita si functie , subrutina sau procedura – este

suficient pentru a o distinge fata de celelalte metode din program .

In Java , in aceeasi clasa putem folosi mai multe metode cu acelasi nume , dar care

difera prin valoarea returnata sau prin lista de parametri . Aceasta practica este

denumita supraincarcarea metodei ( overloading ) .

Mai jos putem vedea o definitie generala a unei metode :

tipRetur numeMetoda(tip1 argument1 , tip2 argument2 , … ) {

// corpul metodei

}

tipRetur poate fi un tip primitiv , un nume de clasa sau cuvantul cheie void , atunci

cand metoda nu returneaza o valoare .

In cazul in care metoda returneaza un obiect tablou , trebuie folosite parantezele

patrate fie dupa tipRetur fie dupa lista de parametri :

int[] creareDomeniu(int inf, int sup) {

// corpul metodei

}

Lista de parametri a metodei este un set de definitii de variabile , separate prin virgula

si incadrate intre paranteze rotunde . Acesti parametri devin variabile locale in corpul

metodei , primind valori la apelarea metodei .

- 47 -

Page 48: Programare Java

In afara cazurilor cand este declarata cu tipul de retur void , o metoda returneaza la

terminarea sa o valoare de un anumit tip . Aceasta valoare trebuie specificata explicit

in punctele de iesire ale metodei , prin cuvantul cheie return .

In listingul de mai jos avem un exemplu de clasa care defineste o metoda care preia

doi intregi si creaza un tablou care contine toate numerele intregi aflate intre cele doua

limite :

class ClasaDomeniu {

int[] creareDomeniu(int inf,int sup) {

int tabl[]=new int[(sup-inf)+1];

for (int i=0;i<tabl.length;i++) {

tabl[i]=inf++;

}

return tabl;

}

public static void main(String argumente[]) {

int unTablou[];

ClasaDomeniu unDomeniu=new ClasaDomeniu();

unTablou=unDomeniu.creareDomeniu(1,10);

System.out.print(“Tabloul : [ “);

for (int i=0;i<unTablou.length;i++) {

System.out.println(unTablou[i]+” “);

}

}

Metoda main() a clasei apeleaza metoda creareDomeniu() prin crearea unui domeniu

marginit inferior , respectiv superior , de valorile 1 si 10 , dupa care foloseste un ciclu

for pentru a afisa valorile noului tablou .

CUVANTUL CHEIE THIS

In corpul unei definitii de metoda putem sa ne referim la obiectul curent – obiectul a

carei metoda a fost apelata . Aceasta poate avea scopul de a folosi variabilele de

instanta ale obiectului sau de a transmite obiectul curent ca argument unei alte metode

.

Pentru a referi obiectul curent in astfel de cazuri se foloseste cuvantul cheie this acolo

unde in mod normal s-ar folosi numele unui obiect .

Acest cuvant cheie se refera la obiectul curent si poate fi folosit oriunde poate aparea

un obiect : in notatia cu punct , ca argument al unei metode , ca valoare de retur

pentru metoda curenta s.a.m.d . Mai jos avem un exemplu de folosire a lui this :

t=this.x; // variabila de instanta x pentru acest obiect

this.resetDate(this); // apeleaza metoda resetDate() definita in clasa curenta si

// transmite obiectul curent

return this; // returneaza obiectul curent

- 48 -

Page 49: Programare Java

In multe cazuri s-ar putea sa nu fie nevoie sa utilizam explicit cuvantul cheie this ,

deoarece este presupus . De exemplu , putem sa ne referim atat la variabilele de

instanta cat si la apelurile de metode definite in clasa curenta prin simpla folosire a

numelui lor , deoarece this este implicit folosit in aceste referinte :

t=x; // variabila de instanta x pentru acest obiect

resetDate(this); // apeleaza metoda resetDate() definita in clasa curenta si

// transmite obiectul curent

Deoarece this este o referinta a instantei curente a clasei trebuie sa o folosim doar in

cadrul corpului unei definitii de metoda de instanta . Metodele de clasa , declarate prin

cuvantul cheie static , nu pot folosi this .

DOMENIUL DE VIZIBILITATE AL VARIABILELOR

Domeniul de vizibilitate este acea parte a programului in care o variabila sau o alta

informatie poate fi folosita . Daca acea parte a programului care defineste domeniul

de vizibilitate al unei variabile isi termina executia variabila nu mai exista .

O variabila cu domeniu de vizibilitate local poate fi folosita doar in cadrul blocului in

care a fost definita . Variabilele de instanta si de clasa poseda un domeniu de

vizibilitate extins la intreaga clasa , deci ele pot fi accesate de oricare dintre metodele

din cadrul clasei .

Atunci cand referim o variabila in cadrul unei metode , Java verifica definitia acesteia

mai intai in domeniul de vizibilitate local , dupa aceea in domeniul exterior imediat

urmator si , in cele din urma , in domeniul metodei curente . Daca variabila nu este

locala Java verifica existenta unei definitii a acesteia ca variabila de instanta sau de

clasa in clasa curenta . Daca Java tot nu gaseste definitia variabilei ocauta pe rand in

fiecare superclasa .

TRANSMITEREA ARGUMENTELOR CATRE METODE

Atunci cand apelam o metoda cu parametri obiect , obiectele sunt transmise in corpul

metodei prin referinta . Orice vom face cu obiectele in cadrul metodei le va afecta

direct . Aceste obiecte pot fi tablouri si alte obiecte continute in tablouri . Atunci cand

transmitem un tablou ca argument intr-o metoda si continutul lui se modifica , este

afectat tabloul original .

Pe de alta parte trebuie sa mentionez ca tipurile de date primitive sunt transmise prin

valoare .

METODE DE CLASA

Relatia dintre variabilele de instanta si cele de clasa este comparabila cu diferenta

dintre modurile de lucru ale metodelor de instanta si de clasa .

- 49 -

Page 50: Programare Java

Metodele de clasa sunt disponibile oricarei instante a clasei si pot fi facute disponibile

altor clase . In plus , spre deosebire de o metoda de instanta , o clasa nu necesita o

instanta a clasei pentru a-I putea fi apelate metodele .

De exemplu, bibliotecile Java contin o clasa denumita Math . Clasa Math defineste un

set de operatii matematice pe care le putem folosi in orice program sau pentru diferite

tipuri numerice :

float radical=Math.sqrt(453.0);

System.out.println(“Cel mai mare dintre x si y este : “+Math.max(x,y));

Pentru a defini metode de clasa se foloseste cuvantul cheie static , pozitionat in fata

definitiei metodei , la fel ca in cazul definirii variabilelor de clasa . De exemplu ,

metoda de clasa max() , folosita in exemplul precedent , ar putea avea urmatoarea

semnatura :

static int(int arg1 , int arg2) {

// corpul metodei

}

Java contine clase de impachetare ( wrapper ) pentru fiecare dintre tipurile de baza .

Lipsa cuvantului cheie static din fata numelui unei metode face ca aceasta sa fie o

metoda de instanta .

CREAREA APLICATIILOR JAVA

Aplicatiile Java sunt programe care ruleaza individual . Aplicatiile difera de

appleturile Java care au nevoie pentru rulare de un browser compatibil Java .

O aplicatie Java consta dintr-una sau mai multe clase ce pot avea orice dimensiune

dorim . Singurul element de care avem neaparat nevoie pentru a rula o aplicatie Java

este o clasa care sa serveasca drept punct de plecare pentru restul programului Java.

Clasa de pornire a aplicatiei are nevoie de un singur lucru : o metoda main() . Aceasta

metoda este prima apelata .

Semnatura metodei main() arata totdeauna astfel :

public static void main (String argumente[]) {

// corpul metodei

}

- public – inseamna ca metoda este disponibila altor clase si obiecte . Metoda

main() trebuie declarata public .

- static – inseamna ca metoda main() este o metoda de clasa

- void – inseamna ca metoda main() nu returmeaza nici o valoare

- main() preia un parametru care este un tablou de siruri . Acesta se foloseste

pentru argumentele programului .

TRASMITEREA DE ARGUMENTE APLICATIILOR JAVA

- 50 -

Page 51: Programare Java

Pentru a transmite argumente unui program Java acestea trebuie adaugate la executie

dupa numele programului :

java ProgramulMeu argument1 argument2

Pentru a transmite argumente care contin spatii acestea trebuie incadrate de ghilimele

duble .

Atunci cand o aplicatie este rulata cu argumente , Java le memoreaza sub forma unui

tablou de siruri , pe care il transmite metodei main() a aplicatiei . Pentru a putea trata

aceste argumente drept altceva decat siruri trebuie mai intai sa le convertim .

- 51 -

Page 52: Programare Java

Programare Java

Curs – 5

FOLOSIREA METODELOR PENTRU INDEPLINIREA SARCINILOR

Metodele sunt partea cea mai importanta a oricarui limbaj de programare orientat obiect deoarece

ele definesc fiecare actiune indeplinita de un obiect .

Clasele si obiectele ofera un cadru de lucru . Variabilele de instanta si de clasa ofera o modalitate

de a defini ceea ce reprezinta aceste clase si obiecte . Doar metodele pot defini comportamentul

unui obiect - lucrurile pe care este capabil sa le realizeze sau modul cum interactioneaza cu alte

clase sau obiecte .

In cursurile anterioare am vazut cum sa definim o metoda si sa lucram cu ea practic . In continuare

vom detalia unele caracteristici care fac metodele sa fie mai eficiente si mai usor de folosit :

- supraincarcarea metodelor ( overloading ) – crearea de metode cu diferite semnaturi si

definitii insa cu acelasi nume

- crearea metodelor constructor – metode care permit initializarea obiectelor , pentru a le

defini starea initiala din momentul crearii lor

- suprascrierea metodelor (overriding ) – crearea unei definitii diferite penttu o metoda care a

mai fost definita in superclasa

- metode de finalizare ( finalizer ) – metode care elibereaza resursele ocupate de un obiect

dupa terminarea lucrului cu un el , inainte ca acesta sa fie inlaturat din sistem

CREAREA DE METODE CU ACELASI NUME SI ARGUMENTE DIFERITE

Un exemplu de astfel de metoda este valueOf() ; metoda apartine clasei java.lang.String . In

general in Java vom intalni des clase care contin mai multe metode cu acelasi nume .

Metodele cu acelasi nume se diferentiaza intre ele prin doua caracteristici :

- numarul argumentelor pe care le preiau

- tipul datelor sau obiectelor fiecarui argument

Aceste doua caracteristici definesc semnatura metodei ; folosirea mai multor metode cu acelasi

nume si semnaturi diferite se numeste supraincarcare .

In exemplul clasei String , metodele valueOf() sunt supraincarcate deoarece preiau ca parametri

tipuri de date diferite .

Supraincarcarea metodelor elimina nevoia de a defini metode complet diferite care sa faca in

principiu acelasi lucru . Supraincarcarea face de asemenea posibila comportarea diferita a

metodelor in functie de argumentele primite .

Metodele valueOf() pot fi folosite pentru a converti diverse tipuri de date sau obiecte in siruri .

Atunci cand apelam o metoda a unui obiect Java verifica numele si argumentele acesteia pentru a

vedea ce metoda va executa .

Pentru a crea o metoda supraincarcata intr-o clasa vom defini metode diferite , cu acelasi nume

insa cu liste de argumente diferite . Diferenta poate consta in numarul de argumente , in tipul de

argumente sau ambele . Java permite supraincarcarea metodelor atat timp cat lista de argumente

este unica pentru acelasi nume de metoda .

Mentionez ca Java nu ia in considerare tipul valorii returnate pentru a face diferentierea metodelor

supraincarcate . Daca incercam sa cream doua metode care difera doar prin tipul valorii de retur

- 52 -

Page 53: Programare Java

vom obtine o eroare inca de la compilare . In plus numele variabilelor pe care le alegem pentru

fiecare argument nu au importanta – tot ceea ce conteaza este numarul si tipul acestora .

In continuare vom detalia un exemplu de metoda supraincarcata . Vom crea intai o clasa care

defineste o forma rectangulara cu patru variabile de instanta , pentru a preciza colturile din stanga-

sus si dreapta-jos ale unui dreptunghi : x1 , y1 , x2 , y2 .

class DreptunghiulMeu {

int x1=0;

int y1=0;

int x2=0;

int y2=0;

}

Atunci cand este creata o noua instanta a clasei noastre toate valorile vor fi initializate cu 0 . In

continuare vom defini o metoda care preia patru argumente intregi si returneaza obiectul

rectangular . Deoarece argumentele au acelasi nume cu variabilele de instanta , in cadrul metodei

vom folosi cuvantul cheie this pentru a referi variabilele de instanta :

DreptunghiulMeu construireDreptunghi ( int x1 , int y1 , int x2, int y2) {

this.x1=x1;

this.y1=y1;

this.x2=x2;

this.y2=y2;

return this;

}

O alta varianta ar fi folosirea obiectelor Point in locul coordonatelor individuale . Pentru a

implementa aceasta varianta putem supraincarca metoda noastra astfel incat lista de argumente sa

contina doua obiecte Point :

DreptunghiulMeu construireDreptunghi ( Point stangaSus , Point dreaptaJos ) {

x1=stangaSus.x;

y1=stangaSus.y;

x2=dreaptaJos.x;

y2=dreaptaJos.y;

return this;

}

Pentru ca metoda anterioara sa functioneze clasa Point trebuie importata la inceputul codului sursa

.

O alta modalitate de a defini un dreptunghi este de a folosi coordonatele coltului din stanga-sus

impreuna cu valorile inaltimii si latimii sale :

DreptunghiulMeu construireDreptunghi(Point stangaSus , int l , int h ) {

x1=stangaSus.x;

y1=stangaSus.y;

x2=(x1+l);

y2=(y1+h); - 53 -

Page 54: Programare Java

return this;

}

Pentru a finaliza exemplul mai cream o clasa , afisareDreptunghi() , care urmeaza sa afiseze

coordonatele dreptunghiului , si o metoda main() care sa apeleze toate aceste metode :

import java.awt.Point;

class DreptunghiulMeu {

int x1=0;

int y1=0;

int x2=0;

int y2=0;

DreptunghiulMeu construireDreptunghi(int x1 , int y1 , int x2 , int y2) {

this.x1=x1;

this.y1=y1;

this.x2=x2;

this.y2=y2;

return this;

}

DreptunghiulMeu construireDreptunghi(Point stangaSus , Point dreaptaJos ) {

x1=stangaSus.x;

y1=stangaSus.y;

x2=dreaptaJos.x;

y2=dreaptaJos.y;

return this;

}

DreptunghiulMeu construireDreptunghi(Point stangaSus , int l , int h) {

x1=stangaSus.x;

y1=stangaSus.y;

x2=(x1+l);

y2=(y1+h);

return this;

}

void afisareDreptunghi() {

System.out.print(“Dreptunghiul meu : <”+x1+”, “+y1);

System.out.println(“, “+x2+”, “+y2+”>”);

}

public static void main(String argumente[]) {

DreptunghiulMeu dreptunghi=new DreptunghiulMeu();

System.out.println(“Apelam construireDreptunghi cu coordonatele 25,25,50,50 : “);

dreptunghi.construireDreptunghi(25,25,50,50);

dreptunghi.afisareDreptunghi();

System.out.println(“***”);

System.out,println(“Apelam construireDreptunghi cu punctele (10,10) , (20,20): “);

dreptunghi.construireDreptunghi(new Point(10,10), new Point(20,20));

dreptunghi.afisareDreptunghi(); - 54 -

Page 55: Programare Java

System.out.println(“***”);

System.out.print(“Apelam construireDreptunghi cu 1 punct (10,10),”);

System.out.println(“ latime 50 si inaltime 50 : “);

dreptunghi.construireDreptunghi( new Point(10,10) , 50 , 50 );

dreptunghi.afisareDreptunghi();

System.out.println(“***”);

}

}

Atunci cand avem mai multe metode care fac lucruri asemanatoare , intr-o metoda putem apela o

alta . De exemplu , in cazul de mai sus , metoda construireDreptunghi care primeste ca argumente

doua obiecte Point poate fi inlocuita cu o versiune mult mai scurta :

DreptunghiulMeu construireDreptunghi(Point stangaSus , Point dreaptaJos) {

return construireDreptunghi(stangaSus.x , stangaSus.y , dreaptaJos.x , dreaptaJos.y );

}

METODE CONSTRUCTOR

In afara de metode obisnuite in clase putem defini si metode constructor .

O metoda constructor este o metoda apelata la crearea unui obiect – cu alte cuvinte , atunci cand

obiectul este construit .

Spre deosebire de alte metode , o metoda constructor nu poate fi apelata direct ; Java apeleaza

metodele constructor in mod automat .

Atunci cand este folosita instructiunea new pentru crearea unui nou obiect , Java executa trei

activitati :

- aloca memorie pentru obiect

- initializeaza variabilele de instanta ale obiectului fie la valorile initiale fie la cele

prestabilite ( 0 pentru numere , null pentru obiecte , false pentru valori booleene si “\0”

pentru caractere )

- apeleaza metodele constructor ale clasei

Chiar daca o clasa nu are definita nici o metoda constructor este totusi posibila crearea unui obiect

. Exista insa cazuri in care dorim sa setam anumite variabile de instanta sau sa apelam alte metode

de care obiectul are nevoie pentru a se initializa .

Prin definirea unor metode constructor in clase , putem seta valorile initiale ale variabilelor de

instanta , putem apela metode pe baza acestor variabile , putem apela metode ale altor obiecte sau

putem seta proprietatile initiale ale unui obiect . Metodele constructor pot fi si ele supraincarcate ,

la fel ca metodele obisnuite , pentru a crea un obiect care are proprietati specifice in functie de

argumentele transmise prin instructiunea new .

METODE CONSTRUCTOR DE BAZA

Constructorii seamana cu metodele obisnuite , cu doua diferente :

- metodele constructor au totdeauna acelasi nume cu cel al clasei

- metodele constructor nu returneaza nimic

- 55 -

Page 56: Programare Java

In exemplul de mai jos vom vedea o clasa Persoana care foloseste o metoda constructor pentru a-si

initializa variabilele de instanta pe baza argumentelor primite de new :

class Persoana {

String nume;

int varsta;

Persoana (String n , int a) {

nume=n;

varsta=a;

}

void printPersoana() {

System.out.print(“Eu sunt “+nume);

System.out.println(“ si am “+varsta+” de ani”);

}

public static void main (String argumente[]) {

Persoana p;

p=new Persoana(“Ion”,50);

p.printPersoana();

System.out.Println(“----“);

p=new Persoana(“Laura”,30);

p.printPersoana();

System.out.println(“----“);

}

}

APELAREA UNEI ALTE METODE CONSTRUCTOR

Am vazut anterior cum o metoda poate apela o alta metoda in cadrul ei .

Acelasi lucru poate fi facut si in cazul constructorilor . Daca avem o metoda constructor ce

reprezinta un comportament oarecum asemanator cu cel al unui constructor existent putem apela

primul constructor din interiorul celui de-al doilea . Java ofera o sintaxa speciala pentru a realiza

acest lucru . Folosim urmatoarea instructiune pentru a apela o metoda constructor definita in clasa

curenta :

this(arg1 , arg2 , arg3);

Folosirea cuvantului cheie this intr-o metoda constructor este similara modului lui de folosire

pentru accesul la variabilele de instanta ale obiectului . In instructiunea anterioara argumentele

primate de this() sunt argumentele metodei constructor . De exemplu , sa luam o clasa care

defineste un cerc folosind coordonatele (x,y) ale centrului si lungimea razei . Clasa CerculMeu

poate avea doi constructori : unul in care este definita raza si unul in care raza primeste valoarea

prestabilita 1 :

class CerculMeu {

int x,y,raza;

CerculMeu (int coordX , int coordY , int lungRaza) {

this.x=coordX;

this.y=coordY;

this.raza=lungRaza;

}

CerculMeu (int coordX , int coordY) {

this(coordX, coordY, 1);

} - 56 -

Page 57: Programare Java

}

A doua metoda constructor din clasa CerculMeu preia doar coordonatele x si y ale cercului .

Deoarece nu este definite nici o raza se foloseste valoarea prestabilita 1 ; se apeleaza apoi prima

metoda constructor care primeste ca argumente coordX , coordY si literalul 1 .

SUPRAINCARCAREA METODELOR CONSTRUCTOR

Ca si metodele obisnuite constructorii pot avea un numar diferit de argumente sau tipuri ale

acestora . Aceasta ne permite sa cream un obiect cu proprietatile dorite sau ofera acestuia

posibilitatea de a-si calcula proprietatile pornind de la date de intrare diferite .

De exemplu , metodele construireDreptunghi , definite in exemplele anterioare , pot constitui niste

metode constructor foarte logice deoarece sunt folosite pentru a initializa variabilele de instanta .

Astfel , in loc de metoda originala construireDreptunghi ( care primea patru parametri ) am putea

crea un constructor .

SUPRASCRIEREA METODELOR

Atunci cand apelam metoda unui obiect , Java cauta definitia metodei respective in clasa obiectului

. Daca nu o gaseste cauta mai sus in ierarhia de clase pana cand gaseste o definitie . Procesul de

mostenire a metodelor ne permite sa definim si sa folosim repetat metode in subclase fara a fi

nevoie sa replicam codul .

Totusi pot exista cazuri cand dorim ca un obiect sa raspunda acelorasi metode , dar sa aiba un

comportament diferit la apelarea acestora . In acest caz , metoda se poate suprascrie . Pentru a

suprascrie o metoda , definim intr-o subclasa o metoda cu aceeasi semnatura ca a unei metode

dintr-o superclasa . Astfel , atunci cand metoda este apelata , metoda din subclasa este gasita prima

si executata in locul celei din superclasa .

CREAREA DE METODE CARE SUPRASCRIU METODE EXISTENTE

Pentru a suprascrie o metoda , in practica trebuie sa cream o metoda cu aceeasi semnatura ( nume ,

tip , valoare returnata , lista de argumente ) ca a metodei din superclasa .

Mai jos cream un exemplu pentru a ilustra supraincarcarea unei metode :

class AfisareClasa {

int x=0;

int y=0;

void afisareDate() {

System.out.println(“x este “+x+” si y este “+y);

System.out.println(“Sunt o instanta a clasei “+this.getClass().getName());

}

}

Cream in continuare si o subclasa a clasei de mai sus , cu o singura diferenta , subclasa contine si

variabila z :

class AfisareSubClasa extends AfisareClasa {

int z=3; - 57 -

Page 58: Programare Java

public static void main(String argumente[]) {

AfisareSubClasa obiect=new AfisareSubClasa();

obiect.afisareDate();

}

}

Deoarece subclasa nu defineste o metoda afisareDate() , Java o cauta in superclasa si o gaseste

acolo pentru a o putea executa . Aceasta metoda insa nu afiseaza si variabila de instanta z .

Sa cream o noua subclasa care sa suprascrie metoda afisareDate() :

class AfisareSubClasa2 extends AfisareClasa {

int z=3;

void afisareDate() {

System.out.println(“x este “+x+” si y este “+y+” iar z este “+z);

System.out.println(“Sunt o instanta a clasei “+this.getClass().getName());

}

public static void main(String argumente[]) {

AfisareSubClasa2 obiect=new AfisareSubClasa2();

obiect.afisareDate();

}

}

Acum , dupa initializarea obiectului AfisareSubClasa2 si apelarea metodei afisareDate() va fi

apelata versiunea existenta in subclasa si nu pe cea din superclasa AfisareDate .

APELAREA METODEI ORIGINALE

De obicei exista doua motive pentru care se face suprascrierea unei metode implementate deja de o

superclasa :

- pentru a inlocui complet definitia metodei originale

- pentru a extinde functionalitatea metodei originale

In multe cazuri practice comportamentul metodei originale trebuie doar completat si nu inlocuit

definitiv , mai ales in cazurile cand se realizeaza acelasi tip de actiuni si in metoda originala si in

cea care o suprascrie . Prin apelarea metodei originale in cadrul metodei de suprascriere putem

adauga numai insusirea suplimentara .

Pentru a apela metoda originala in cadrul metodei de suprascriere folosim cuvantul cheie super . In

acest fel apelul metodei este transferat mai sus in cadrul ierarhiei de obiecte :

void metodaMea ( String a , String b ) {

//cod sursa

super.metodaMea(a,b);

//cod sursa

}

Cuvantul cheie super este asemanator cuvantului cheie this , deoarece este o denumire generica

pentru superclasa clasei curente . Il putem folosi oriunde am putea folosi si this , insa super refera

superclasa nu clasa curenta .

- 58 -

Page 59: Programare Java

Sa ne amintim de cele doua metode afisareDate() diferite , folosite anterior .

In loc sa copiem majoritatea codului metodei superclasei in subclasa , putem modifica metoda

superclasei astfel incat ulterior sa se poata adauga cu usurinta o caracteristica suplimentara :

// din AfisareClasa

void afisareDate() {

System.out.println(“Sunt o instanta a clasei “+this.getClass().getName());

System.out.println(“X este “+x);

System.out.println(“Y este “+y);

}

Apoi , cand suprascriem metoda afisareDate() in subclasa putem apela metoda originala si adauga

doar codul suplimentar :

// din AfisareSubClasa2

void afisareDate() {

super.afisareDate();

System.out.println(“Z este “+z);

}

SUPRASCRIEREA CONSTRUCTORILOR

Din punct de vedere tehnic constructorii nu pot fi suprascrisi . Pentru ca au totdeauna acelasi nume

ca al clasei curente , metodele constructor nu se mostenesc ci se creaza altele noi . Acest sistem

este multumitor in marea majoritate a cazurilor ; atunci cand este apelata metoda constructor a

clasei se apeleaza si metoda constructor cu aceeasi semnatura pentru toate superclasele . Din

aceasta cauza initializarea se face pentru toate partile clasei pe care o mostenim .

Totusi , atunci cand definim metode constructor pentru clasa noastra putem modifica felul in care

este initializat obiectul nu doar prin initializarea noilor variabile adaugate clasei , ci si prin

modificarea continutului variabilelor deja prezente . Pentru aceasta vom apela explicit metodele

constructor ale superclasei si apoi vom modifica variabilele dorite .

Pentru a apela o metoda obisnuita apartinand superclasei vom folosi sintaxa

super.nume_metoda(lista_argumente) . Deoarece metodele constructor nu au nume sub care pot fi

apelate vom folosi urmatoarea forma :

super(arg1 , arg2 , ... );

Retinem ca Java are o regula stricta pentru folosirea metodei super() : aceasta trebuie sa fie prima

instructiune folosita in cadrul constructorului . Daca nu apelam super() explicit in cadrul

constructorului Java face acest lucru implicit , folosind super() fara argumente . Deoarece apelarea

super() trebuie sa fie prima instructiune nu putem folosi un cod de genul :

if (conditie==true)

super(1 , 2 , 3); // apelarea unui constructor al superclasei

else

super( 1 , 2 ); // apelarea unui alt constructor

- 59 -

Page 60: Programare Java

La fel ca in folosirea this(...) intr-o metoda constructor , super(...) apeleaza metoda constructor

pentru superclasa imediat urmatoare ( care la randul sau va apela constructorul superclasei sale si

asa mai departe ) . Retinem ca in superclasa trebuie sa existe un constructor cu semnatura

respectiva pentru ca apelul super() sa functioneze . Compilatorul Java verifica aceste lucruri atunci

cand incercam sa compilam fisierul sursa .

Nu trebuie sa apelam constructorul din superclasa care are aceeasi semnatura cu cea a

constructorului clasei noastre ; trebuie doar sa apelam constructorul pentru valorile pe care dorim

sa le initializam . De fapt , putem crea o clasa care are constructori cu semnaturi total diferite de

oricare dintre constructorii superclasei .

In exemplul urmator vom prezenta o clasa PunctCuNume care extinde clasa Point a pachetului

java.awt . Clasa Point are un singur constructor care preia argumentele x si y si returneaza un

obiect Point . PunctCuNume contine o variabila de instanta suplimentara si defineste un

constructor care initializeaza x , y si numele .

import java.awt.Point;

class PunctCuNume ( int x , int y , String nume ) {

super(x,y);

this.nume=nume;

}

public static void main(String argumente[]) {

PunctCuNume pn=new PunctCuNume(5,5,”PunctulA”);

System.out.println(“x este “+pn.x);

System.out.println(“y este “+pn.y);

System.out.println(“Numele este “+pn.nume);

}

}

Metoda constructor definita aici pentru PunctCuNume apeleaza metoda constructor a clasei Point

pentru a initializa variabilele de instanta x si y . Chiar daca am putea initializa si singuri , explicit ,

variabilele x si y exista posibilitatea sa existe si alte lucruri care s-ar intampla la initilizarea

obiectelor Point ; din aceasta cauza este mai bine sa apelam metodele constructor aflate deasupra

in ierarhie , pentru a fi siguri ca totul se configureaza corect .

METODE DE FINALIZARE

Metodele de finalizare sunt opusul metodelor constructor . O metoda constructor este folosita

pentru a initializa un obiect iar metodele de finalizare sunt apelate chiar inainte de distrugerea

obiectului si recuperarea memoriei ocupate .

Metoda de finalizare este finalize() . Clasa Object defineste o metoda de finalizare prestabilita ,

care nu face nimic ( este vida ) . Pentru a crea o metoda de finalizare pentru propriile clase putem

suprascrie metoda finalize() folosind semnatura :

protected void finalize() throws Throwable {

super.finalize();

}

- 60 -

Page 61: Programare Java

In cadrul metodei finalize() putem specifica toate actiunile de “curatare” pe care dorim sa le

realizam in legatura cu obiectul . De asemenea putem apela super.finalize() pentru a permite

superclasei clasei noastre sa finalizeze obiectul daca este nevoie .

Putem apela metoda finalize() oricand – este o metoda ca oricare alta . Totusi apelarea ei nu

semnaleaza sistemului distrugerea obiectului si recuperarea memoriei ocupate . Numai stergerea

tuturor referintelor la obiectul respectiv duce la marcarea lui pentru distrugere .

Metodele de finalizare sunt folosite de obicei pentru optimizarea distrugerii unui obiect – de

exemplu , pentru distrugerea referintelor catre alte obiecte . In marea majoritate a cazurilor practice

nu este nevoie se folosim deloc metoda explicita finalize() .

- 61 -

Page 62: Programare Java

Programare Java

Curs – 6

CREAREA DE PROGRAME INTERACTIVE PENTRU WEB

Prima oara cand au aparut pe scara larga aplicatiile Java pentru web a fost in 1995 , atunci cand

Netscape Navigator a inceput sa ruleze applet-uri .

In general o aplicatie Java dedicata utilizarii pe web , in cadrul unei pagini HTML , se numeste applet

si are o structura diferita fata de o aplicatie normala scrisa in limbajul Java .

DIFERENTA INTRE APPLET-URI SI APLICATII

Aceasta diferenta consta in principal in modul cum acestea sunt rulate .

Aplicatiile sunt rulate prin intermediul unui interpretor Java care incarca fisierul clasa principal al

aplicatiei . Acest lucru se face de obicei din linia de comanda falosind utilitarul “java.exe” al

pachetului Java2 SDK ( sau JDK in versiunile mai vechi ) .

Pe de alta parte , applet-urile sunt rulate de orice browser care suporta Java – cum ar fi Firefox,

Chrome, Safari , Internet Explorer , Sun HotJava sau Opera . Applet-urile pot fi testate si cu ajutorul

utilitarului “appletviewer.exe” , inclus in pachetul Java2 SDK . Trebuie mentionat ca “appletviewer”

ignora toate celelalte elemente ale paginii web in care inseram applet-ul nostru scris in Java .

Pentru a rula un applet acesta trebuie inglobat intr-o pagina web folosind tag-uri HTML , in acelasi

mod in care sunt inglobate imagini sau alte elemente . Atunci cand un utilizator cu un browser

compatibil cu Java incarca o pagina web care contine un applet , browser-ul trajsfera codul applet-ului

de pe serverul web si il executa pe sistemul local al utilizatorului . Nu este nevoie de un interpretor

Java separat – el este inclus in browser . Ca orice aplicatie , un applet Java contine un fisier clasa si

orice alte clase externe necesare rularii . Biblioteca de clase standard a Java este inclusa automat .

Deoarece applet-urile Java ruleaza in cadrul unui browser Java , o parte din efortul crearii unei

interfete utilizator este eliminata ; exista deja o fereastra in care applet-ul poate rula , un loc unde sa se

afiseze grafica si de unde sa se primeasca datele de intrare precum si interfata browser-ului .

OBS : Este posibil ca un program Java sa functioneze atat ca applet cat si ca aplicatie independenta .

Cu toate ca pentru crearea acestor tipuri de programe se folosesc proceduri separate , acestea nu intra

in conflict una cu alta . Caracteristicile specifice applet-urilor vor fi ignorate atunci cand programul

ruleaza ca aplicatie si viceversa .

ALEGEREA VERSIUNII DE JAVA PENTRU DEZVOLTARE

In cazul crearii de applet-uri Java pentru web un programator mai are o problema suplimentara in afara

de preogramarea propriu-zisa ; programul sau trebuie sa poata rula pe toate browser-ele existente ( mai

realist vorbind pe cat mai multe dintre ele ) .

In acest moment Java 1.02 este singura versiune de limbaj suportata absolut complet de Microsoft

Internet Explorer si browserele bazate pe el ( aplicatii ce detin in jur de 75 de procente din piata

browser-elor ) . Netscape si Microsoft au implementat si versiunile Java 1.1 si 2 dar implementarile

- 62 -

Page 63: Programare Java

mai produc anumite surprize neplacute , in unele cazuri existand applet-uri care nu functioneaza corect

in cazul programarii lor folosind ultima versiune a limbajului .

Sun a gasit o modalitate de a ocoli aceste neajunsuri creand un program add-on ( complementar )

pentru browser-e , denumit Java Plug-in , care ne permite sa utilizam imbunatatirile aduse de Java 1.2

sau Java 2 . Acest program add-on este continut in pachetul JDK 1.2 si in toate celelate versiuni ale

mediului de dezvoltare : 1.3 si 1.4.

Java 2 a fost proiectat astfel incat un program care foloseste numai facilitatile Java 1.02 sa se poata

compila si sa ruleze cu succes in cadrul unui browser compatibil Java .

Daca un applet foloseste una dintre facilitatile introduse de Java 1.1 sau Java 2 programul nu va rula pe

browser-ele care nu suporta aceste versiuni si care nu au instalat add-on-ul de care aminteam mai sus .

De multe ori imbunatatirile aduse limbajului de versiunile 1.1 sau 2 nici nu sunt vitale pentru

aplicatiile de tip applet , gasindu-si o utilitate mult mai mare in domeniul aplicatiilor Java

independente .

In unele cazuri de applet-uri scrise pentru Java 1.02 compilatorul ne va atentiona ca anumite elemente

au fost inlocuite si ca exista o solutie mai buna ; aceste atentionari ( warnings ) nu sunt mesaje de

eroare ale compilatorului, SDK-ul creand un fisier clasa compilat si atragand doar atentia

programatorului.

RESTRICTII DE SECURITATE ALE APPLET-URILOR

Deoarece applet-urile Java sunt executate pe sistemul local al utilizatorului exista unele restrictii foarte

serioase referitoare la activitatile de care este capabil un applet . Daca aceste restrictii nu ar exista un

programator Java ar putea scrie fara probleme un program care sa stearga toate fisierele de pe un hard

disk , sa colecteze informatii private sau sa realizeze diferite brese in securitatea sistemului .

Ca regula generala , applet-urile Java functioneaza dupa principiul “better safe than sorry “ ; unui

applet ii sunt interzise urmatoarele activitati :

- sa citeasca sau sa scrie pe sistemul local al utilizatorului

- sa comunice cu un alt site decat cel de unde provine pagina web ce contine applet-ul

- sa ruleze programe executabile in sistemul local al utilizatorului

- sa incarce programe din sistemul utilizatorului ( executabile sau biblioteci partajate )

Toate aceste reguli se aplica applet-urilor in mod normal dar exista si posibilitatea ( din configurarea

browser-elor ) de a modifica nivelul de securitate dorit , permitand accesul din anumite directoare sau

conexiuni catre anumite site-uri .

De exemplu , utilitarul “appletviewer.exe” permite definirea unei liste de control al accesului pentru

directoarele unde applet-ul poate citi sau scrie fisiere . In practica insa trebuie sa tinem seama de

posibilitatea de a intalni restrictii de securitate maxime iar pentru evitarea problemelor programatorul

trebuie sa tina seama de actiunile care ii sunt teoretic interzise unui applet .

O facilitate nou introdusa de Java 2 este foarte importanta in problema securitatii ; noua versiune a

limbajului permite folosirea unor controale de securitate specifice care pot fi introduse sau eliminate

din applet-uri si aplicatii . Aceste elemente dau posibilitatea unui utilizator web sa acorde “incredere”

unui applet astfel incat acesta sa poata rula fara restrictii pe sistemul local .

CREAREA APPLET-URILOR

- 63 -

Page 64: Programare Java

Un program Java contine o metoda main() , folosita pentru crearea obiectelor , stabilirea variabilelor

de instanta si apelarea altor metode .

Applet-urile nu poseda o metoda main() care sa fie apelata automat la lansarea programului . In schimb

exista mai multe metode apelate in diferite puncte ale executiei unui applet .

Toate applet-urile sunt subclase ale clasei Applet , care apartine pachetului java.applet . Clasa Applet

prezinta doua tipuri de comportament , care trebuie sa fie comune tuturor applet-urilor :

- capacitatea de a opera ca parte a browser-ului si de a trata evenimente ( cum ar fi de exemplu

incarcarea paginii in browser )

- capacitatea de a prezenta o interfata grafica pentru utilizator si de a prelua date de intrare de la

utilizator

Cu toate ca un applet poate folosi orice alte clase are nevoie , clasa Applet este clasa principala care

declanseaza executia unui applet . Subclasele pe care le vom crea , apartinand clasei Applet , vor avea

formula :

public class appletNou extends java.applet.Applet {

// cod sursa

}

Toate applet-urile trebuie declarate public deoarece clasa Applet este o clasa publica . Aceasta cerinta

este valabila numai pentru clasa principala a applet-ului ; orice alte clase externe pot fi publice sau

private .

Atunci cand un browser compatibil Java intalneste un applet Java intr-o pagina web , clasa applet-ului

este incarcata impreuna cu celelalte clase externe folosite . Browser-ul creaza automat o instanta a

clasei applet-ului si apeleaza metode ale clasei Applet atunci cand au loc anumite evenimente .

Diferite applet-uri care folosesc aceeasi clasa folosesc instante diferite deci vom putea introduce mai

multe copii ale applet-ului in aceeasi pagina si fiecare se va comporta diferit .

PRINCIPALELE ACTIVITATI ALE APPLET-URILOR

In locul metodei main() , applet-urile poseda metode care sunt apelate la aparitia anumitor evenimente

pe parcursul rularii applet-ului .

Un exemplu de astfel de metoda este paint() care este apelata ori de cate ori fereastra applet-ului

trebuie afisata sau redesenata .

In mod prestabilit aceste metode sunt nule – ele nu fac practic nimic . De exemplu metoda paint() ,

mostenita de la clasa Applet , este o metoda nula . Pentru a afisa ceva in fereastra applet-ului metoda

paint() trebuie suprascrisa cu un comportament care sa permita afisarea de text , grafica sau alte

elemente .

a. Initializarea

Initializarea apare o data cu incarcarea applet-ului . Initializarea poate consta in crearea obiectelor de

care are nevoie applet-ul , setarea starii initiale , incarcarea unor imagini sau fonturi sau setarea unor

parametri . Pentru a defini codul de initializare al unui applet trebuie suprascrisa metoda init() :

public void init() {

// codul sursa

}

- 64 -

Page 65: Programare Java

b. Pornirea

Un applet este pornit dupa initializare . Pornirea poate aparea si daca applet-ul a fost anterior oprit . De

exemplu un applet este oprit daca utilizatorul browser-ului urmeaza o legatura catre o alta pagina si

este pornit din nou atunci cand utilizatorul revine in pagina care contine applet-ul .

Pornirea poate aparea de mai multe ori pe parcursul ciclului de viata al unui applet , insa initializarea

apare doar o data . Pentru a defini codul de pornire al unui applet trebuie suprascrisa metoda start() :

public void start() {

// codul sursa

}

Codul metodei start() poate contine trimiterea anumitor mesaje obiectelor externe sau specificarea intr-

un anumit mod a faptului ca applet-ul isi incepe rularea .

c. Oprirea

Oprirea si pornirea merg una alaturi de cealalta . Oprirea apare atunci cand utilizatorul paraseste

pagina care contine applet-ul curent sau atunci cand applet-ul se opreste singur apeland metoda stop() .

In mod prestabilit orice fire de executie ( threads ) pe care applet-ul le-a lansat isi vor continua

executia si dupa ce utilizatorul paraseste pagina . Prin suprascriere metodei stop() putem suspenda

executia acestor fire si le putem reporni daca applet-ul este vizualizat din nou . In continuare se

prezinta o forma a metodei stop() :

public void stop() {

// codul sursa

}

d. Distrugerea

Metoda destroy() permite applet-ului sa-si faca “curatenie” chiar inainte de a se elibera memoria

alocata sau de a parasi browser-ul . Putem folosi aceasta metoda pentru a distruge orice fire de

executie sau pentru a elibera orice alte obiecte care ruleaza . De obicei nu se suprascrie metoda

destroy() decat daca exista anumite resurse care trebuie neaparat eliberate , cum ar fi fire de executie

create de applet . Pentru a defini codul de distrugere al unui applet trebuie suprescrisa metoda destroy()

:

public void destroy() {

// codul sursa

}

In cursurile anterioare a aparut un element inrudit cu destroy() : metoda finalize() . Diferenta intre

aceste doua metode consta in faptul ca metoda destroy() se aplica doar applet-urilor iar finalize() este o

metoda generica , ce permite unui obiect de orice tip sa-si elibereze resursele .

Java poseda un recuperator automat al resurselor utilizate ( garbage collector ) , care administreaza

memoria in locul nostru . Acesta recupereaza memoria ocupata de resurse dupa ce programul nu le mai

foloseste , asa ca , in mod normal , nu trebuie sa folosim decat foarte rar metode ca destroy() sau

finalize() .

e. Desenare

Desenarea este modul prin care un applet afiseaza ceva pe ecran : text , linii , imagini , etc.

- 65 -

Page 66: Programare Java

Desenarea poate aparea de foarte multe ori pe parcursul ciclului de viata al unui applet : o data dupa

initializarea applet-ului , alta data atunci cand fereastra browser-ului este adusa in prim plan , alta data

atunci cand fereastra browser-ului este mutata si asa mai departe . Pentru a se putea afisa ceva metoda

paint() , din subclasa noastra Applet , trebuie suprascrisa . Metoda paint() arata in felul urmator :

public void paint (Graphics g) {

// codul sursa

}

Trebuie sa observam ca , spre deosebire de celelalte metode descrise anterior , metoda paint() preia un

argument : o instanta a clasei Graphics . Acest obiect este creat si transmis metodei paint() de catre

browser , deci nu trebuie sa ne facem probleme legate de definirea sa . Totusi , nu trebuie sa uitam sa

importam clasa Graphics din pachetul java.awt in codul applet-ului nostru :

import java.awt.Graphics;

REALIZAREA UNUI APPLET

In cursul 3 s-a creat un applet Java denumit “Palindrom.java” cu scopul de a detalia conceptul de

mostenire . Acum revenim la acelasi exemplu privindu-l acum doar ca applet :

1: import java.awt.Graphics;

2: import java.awt.Color;

3: import java.awt.Font;

4:

5: public class Palindrom extends java.applet.Applet {

6: Font f=new Font("TimesRoman",Font.BOLD,36);

7:

8: public void paint(Graphics monitor) {

9: monitor.setFont(f);

10: monitor.setColor(Color.red);

11: monitor.drawString("AbbA",5,40);

12: }

13: }

Acest applet suprascrie metoda paint() . Deoarece applet-ul afiseaza doar cateva cuvinte pe ecran nu

este nevoie de nici o initializare . Astfel nu este nevoie de metodele start() , stop() sau init() .

Metoda paint() este locul unde se face toata treaba . Obiectul Graphics transmis metodei paint()

pastreaza starea sistemului grafic , prin care se cunosc atributele curente ale suprafetei de desenare .

Starea mai contine si detalii privind fontul curent sau culoarea folosita pentru operatiile de desenare .

Liniile 9 si 10 definesc fontul si culoarea folosite pentru operatiile grafice . Obiectul Font este pastrat

in variabila de instanta f iar obiectul reprezentand culoarea rosie este memorat in variabila red a clasei

Color .

Linia 11 foloseste fontul si culoarea curente pentru a desena sirul “AbbA" in pozitia 5 , 40 .

Reamintesc ca pozitia 0 pentru x si y este punctul din stanga – sus al suprafetei de desenare a applet-

ului , cu valoarea y crescand in jos asa incat valoarea 40 deplaseaza textul in jos .

Daca implementam in clasa metodele corecte pentru applet – init() , start() , stop() , sau paint() – atunci

applet-ul nostru va functiona corect fara a avea nevoie de un punct de start explicit .

- 66 -

Page 67: Programare Java

INSERAREA UNUI APPLET INTR-O PAGINA WEB

Dupa ce am creat clasa sau clasele care compun applet-ul si le compilam in fisiere de tip class trebuie

sa cream o pagina web in care sa introducem applet-ul .

Applet-urile se insereaza intr-o pagina folosind eticheta HTML <applet> , o comanda care

functioneaza asemanator altor elemente HTML . Exista de asemenea diferite utilitare pentru

dezvoltarea de pagini web – ca Microsoft FrontPage sau Macromedia Dreamweaver – care pot fi

folosite pentru a insera applet-uri in paginile noastre web fara a folosi explicit cod HTML .

Scopul tag-ului <applet> este de a pozitiona applet-ul nostru in pagina web si de a controla modul cum

arata acesta in relatie cu celelalte parti ale paginii .

Browser-ele compatibile Java folosesc informatia continuta de aceasta eticheta pentru a gasi si executa

fisierele compilate cu clasele applet-ului .

Eticheta <applet> este de fapt o extensie speciala a limbajului HTML , care permite includerea applet-

urilor Java in paginile web ; eticheta este suportata de toate browser-ele compatibile Java .

Mai jos avem codul sursa HTML pentru o pagina in care am inserat applet-ul Palindrom :

<html>

<head>

<title>Pagina cu applet</title>

</head>

<body>

<p>Palindromul prezentat este :<br>

<applet code=”Palindrom.class” width=600 height=100>

Nu aveti browser compatibil Java

</applet>

</body>

</html>

Tag-ul <applet> de mai sus contine trei atribute esentiale :

- code - specifica numele clasei principale a applet-ului

- width - specifica latimea ferestrei applet-ului in pagina web

- height - specifica inaltimea ferestrei applet-ului in pagina web

Fisierul care contine clasa indicata de atributul CODE trebuie sa se afle in acelasi director ca pagina

web care contine applet-ul , cu exceptia cazurilor cand folosim atributul CODEBASE pentru a

specifica un alt director .

WIDTH si HEIGHT sunt atribute necesare deoarece browser-ul trebuie sa stie cat spatiu sa aloce

applet-ul in pagina . Este usor sa desenam intr-o zona exterioara ferestrei applet-ului asa ca trebuie sa

ne asiguram ca am prevazut o fereastra suficient de mare .

Intre etichetele <applet> si </applet> pot fi incluse si alte elemente de pagina web , cum ar fi text sau

imagini . Acestea sunt afisate in pagina web doar de browser-ele care nu sunt compatibile Java ; este in

general bine sa le includem deoarece utilizatorii sunt astfel anuntati ca nu pot vedea un applet pentru

ca browser-ul lor nu este pus la curent . Daca nu specificam nimic intre aceste doua etichete browser-

ele incompatibile Java nu vor afisa nimic in locul applet-ului .

In exemplul de mai sus cei care nu au browser compatibil Java vor vedea textul :

“Nu aveti browser compatibil Java”

- 67 -

Page 68: Programare Java

in locul applet-ului .

Cele trei atribute ale tag-ului <applet> prezentate mai sus sunt cele de baza ; totusi , eticheta <applet>

contine si alte atribute , care pot ajuta la integrarea ,mai eficienta a applet-ului in structura generala a

paginii web :

a. atributul ALIGN

Acest atribut defineste modul cum va fi aliniat applet-ul in pagina web , relativ la celelalte elemente

ale paginii ; atributul poate lua urmatoarele valori :

- left - aliniaza applet-ul la stanga textului care urmeaza in pagina dupa applet

- right - aliniaza applet-ul la dreapta textului care urmeaza in pagina dupa applet

- texttop - aliniaza partea superioara a applet-ului cu partea superioara a celui mai inalt text de

pe linie

- top - aliniaza applet-ul cu cel mai de sus element prezent pe linie ( un alt applet , o imagine

sau un text )

- absmiddle - aliniaza mijlocul applet-ului cu mijlocul celui mai mare element de pe linie

- middle - aliniaza mijlocul applet-ului cu mijlocul liniei de baza a textului

- baseline - aliniaza partea inferioara a applet-ului cu linia de baza a textului

- bottom - acelasi lucru ca si baseline

- absbottom - aliniaza partea inferioara a applet-ului cu cel mai de jos element de pe linie

Pentru a finaliza formatarea specifica prin atributul ALIGN , putem folosi eticheta de terminare de

rand <br> , impreuna cu atributul CLEAR , acesta din urma putand lua trei valori :

- left - continua afisarea restului paginii web la urmatoarea margine libera din stanga

- right - continua afisarea restului paginii web la urmatoarea margine libera din dreapta

- all - continua afisarea restului paginii web la urmatoarea margine libera din stanga si din

dreapta

b. atributele HSPACE SI VSPACE

Atributele HSPACE si VSPACE sunt folosite pentru a determina spatiul , in numar de pixeli , intre

applet si textul inconjurator . HSPACE controleaza spatiul orizontal in stanga si in dreapta applet-ului

iar VSPACE controleaza spatiul vertical existent deasupra si dedesuptul applet-ului .

c. CODE SI CODEBASE

Aceste doua atribute sunt folosite pentru a indica unde pot fi gasite fisierele cu clasa principala a

applet-ului si alte fisiere necesare rularii acestuia . Aceste atribute sunt folosite de un browser Java in

momentul in care incearca sa ruleze applet-ul .

CODE indica numele fisierului care contine clasa principala a applet-ului . Cand CODE este folosit

fara atributul optional CODEBASE fisierul care contine clasa va fi cautat in acelasi loc in care se afla

pagina web care contine applet-ul .

In cadrul atributului CODE trebuie specificata si extensia .class .

Atributul CODEBASE se foloseste pentru a indica browser-ului sa caute applet-ul si alte fisiere

necesare rularii acestuia intr-un alt director . CODEBASE indica un alt director sau chiar un alt site de

unde urmeaza a se incarca clasele :

<applet code=”ClasaMea.class” codebase=http://www.site.com/clasejava

height=40 width=400>

- 68 -

Page 69: Programare Java

</applet>

Trebuie mentionat ca eticheta <applet> este folosita special pentru a insera programe Java in paginile

web . In prezent exista si alte tipuri de programe care ruleaza interactiv intr-o pagina . Pentru a trata

toate aceste tipuri de programe fara a fi nevoie de cate o eticheta pentru fiecare explicit , specificatiile

HTML au introdus si eticheta <object> .

Aceasta eticheta este folosita pentru toate obiectele – programe interactive sau alte elemente externe –

care pot fi prezente drept parte a unei pagini web .

Eticheta are urmatoarea forma :

<object classid=”java:Clasa.class” codebase=”clasejava” height=40 width=400>

</object>

Trecerea de la eticheta <applet> la <object> presupune doar cateva modificari :

- atributul code trebuie inlocuit cu classid ; in plus , inainte de numele clasei applet-ului trebuie

specificat “java:” .

- eticheta <applet> se inlocuieste cu <object>

In rest atributele raman aceleasi .

TRANSFERUL DE PARAMETRI CATRE APPLET-URI

In aplicatiile Java putem transmite parametri metodei main() specificand argumente in linia de

comanda . Apoi putem prelucra acesti parametri in corpul clasei , aplicatia comportandu-se

corespunzator argumentelor primite .

In schimb applet-urile nu poseda o linie de comanda . Applet-urile pot obtine diferite date de intrare

din fisierul HTML care contine eticheta <applet> sau <object> , folosind parametri . Pentru a defini si

trata parametri intr-un applet avem nevoie de doua lucruri :

- o eticheta de parametru in fisierul HTML

- codul din cadrul applet-ului care sa trateze acesti parametri

Parametrii unui applet sunt compusi din doua parti : un nume , care este ales de dumneavoastra , si o

valoare , care determina valoarea respectivului parametru . De exemplu , putem indica intr-un applet

culoarea unui text folosind un parametru cu numele culoare si valoarea rosu . Putem determina viteza

de derulare a unei animatii folosind un parametru cu numele viteza si o anumita valoare .

In fisierul HTML care contine applet-ul , fiecare parametru este indicat folosind eticheta <param> ,

care contine doua atribute , pentru nume si valoare , denumite NAME si VALUE . Eticheta <param>

se introduce intre etichetele <applet> de inceput si de sfarsit de container :

<applet cade=”Clasa.class” width=100 height=100>

<param name=font value=TimesRoman>

<param name=dim value=24>

Aici este un applet Java

</applet>

- 69 -

Page 70: Programare Java

Exemplul de mai sus defineste doi parametri pentru applet-ul “Clasa” : unul , denumit font , care are

valoarea TimesRoman si celalalt , denumit dim , care are valoarea 24 .

Folosirea etichetei <param> este aceeasi pentru applet-urile care folosesc tag-ul <object> in loc de

<applet> .

Parametri sunt transmisi applet-ului la incarcarea acestuia . In metoda init() a applet-ului putem obtine

acesti parametri folosind metoda getParameter() . Aceasta preia ca argument un sir ce reprezinta

numele parametrului cautat si intoarce un sir care contine valoarea respectivului parametru . Pentru a

obtine valoarea parametrului font din fisierul HTML de mai sus , metoda init() ar trebui sa contina :

String numeFont = getParameter(“font”);

Numele parametrilor specificati in eticheta <param> si numele parametrilor metodei getParameter()

trebuie sa fie identice , inclusiv majusculele sau minusculele folosite . Cu alte cuvinte , <param

name=popescu”> este diferit de <param name=Popescu> .

Retineti ca daca parametrul asteptat nu a fost specificat in fisierul HTML , metoda getParameter()

intoarce valoarea null . De obicei , ar trebui testata valoarea null a parametrului si sa oferim o valoare

implicita . ca in exemplul de mai jos :

if (numeFont==null )

numeFont=”Courier”;

Mai trebuie reamintit din nou ca metoda getParameter() returneaza un sir ; daca dorim ca parametrul sa

fie de alt tip de obiect sau data trebuie sa il convertim explicit . Pentru a trata parametrul dim si a-l

atribui unei variabile intregi , numita dimensiunea , am putea folosi urmatorul cod :

int dimensiunea ;

String s = getParameter(“dim”);

if (s==null)

dimensiunea =12;

else

dimensiunea = Integer.parseInt(s);

In continuare sa vedem un exemplu de applet care foloseste aceasta tehnica . Vom modifica applet-ul

Palindrom pentru a afisa alte texte . Numele este transmis applet-ului printr-un parametru HTML .

Proiectul va primi numele PalindromNou .

Primul lucru pe care trebuie sa il adaugam acestei clase este o variabila in care va fi pastrata valoarea

parametrului palindrom . Deoarece vom folosi acest nume in cadrul applet-ului , vom adauga o

variabila de instanta dupa numele variabilei pentru font :

String palindrom;

Pentru a seta valoarea numelui , trebuie sa obtinem parametrul . Cel mai bun loc de obtinere a

parametrilor applet-ului este in cadrul metodei init() . Metoda init() este definita asemanator cu paint()

– publica , fara argumente si fara tip de retur . De asemenea trebuie sa ne asiguram ca testam valoarea

null a parametrului . Daca palindromul nu este specificat se va afisa implicit textul “Dennis and Edna

sinned” , ca in exemplul de mai jos :

public void init() {

palindrom = getParameter(“palindrom”);

if (palindrom==null)

palindrom=”Dennis and Edna sinned”;

- 70 -

Page 71: Programare Java

}

O data adaugata aceasta metoda tot ce na mai ramane este sa modificam metoda paint() . Metoda

originala drawString() arata astfel :

ecran.drawString(“AbbA”,5,40);

Pentru a desena noul sir pe care il stocam in variabila de instanta palindrom , tot ceea ce trebuie sa

facem este sa inlocuim variabila cu sirul :

ecran.drawString(palindrom,5,40);

In continuare prezentam listingul complet al aplicatiei applet PalindromNou :

1: import java.awt.Graphics;

2: import java.awt.Color;

3: import java.awt.Font;

4: // liniile 1,2,3 se pot inlocui cu : import java.awt.* ;

5: public class PalindromNou extends java.applet.Applet {

6: Font f=new Font("TimesRoman",Font.BOLD,36);

7: String palindrom;

8: public void paint(Graphics ecran) {

9: ecran.setFont(f);

10: ecran.setColor(Color.red);

11: ecran.drawString(palindrom,5,40);

12: }

13: public void init() {

14. palindrom = getParameter(“palindrom”);

15. if (palindrom==null)

palindrom=”Dennis and Edna sinned”;

16: }

17: }

In continuare vom crea si fisierul HTML care va contine acest applet :

<html>

<head>

<title>Pagina noua cu palindrom</title>

</head>

<body>

<p>

<applet code=”PalindromNou.class” width=600 height=100>

<param name=palindrom value=”No sir prefer prison”>

Browser-ul nu suporta Java

</applet>

</body>

</html>

Daca nu este specificata nici o valoare pentru parametrul palindrom textul implicit este “Dennis and

Edna sinned” .

- 71 -

Page 72: Programare Java

AMPLASAREA APPLET-URILOR IN WEB

Dupa ce am obtinut un applet care functioneaza corespunzator putem face applet-ul disponibil in

World Wide Web .

Applet-urile Java sunt introduse pe un server web in aceasi mod ca si fisierele HTML , imaginile sau

alte fisiere multimedia . Applet-ul trebuie stocat intr-un director accesibil serverului web – de cele mai

multe ori in acelasi director care contine si pagina web ce inglobeaza applet-ul .

Serverul web trebuie configurat pentru a oferi applet-uri Java browser-elor ce suporta acest limbaj .

Exista cateva fisiere ce trebuie incarcate pe un server web :

- pagina web ce contine applet-ul

- toate fisierele .class folosite de applet si care nu fac parte din biblioteca de clase standard a

Java

In general daca stim cum sa publicam o pagina web , fisiere cu imagini si alte elemente multimedia

vom putea sa publicam fara probleme si applet-uri Java pe site-ul nostru .

ARHIVE JAVA

Modalitatea standard de amplasare a unui applet Java intr-o pagina web este de a folosi etichetele

<applet> si <object> pentru a indica numele clasei primare a applet-ului . Se foloseste apoi un browser

compatibil Java care transfera si executa applet-ul . Orice alte clase sau fisiere folosite de applet sunt

transferate de pe serverul web .

Problema cu rularea in acest fel a applet-urilor este ca fiecare fisier de care are nevoie applet-ul , fie

acesta o clasa externa , un fisier imagine , audio , text sau orice altceva – necesita o conexiune separata

de la browser la serverul web care contine fisierul . Deoarece intervalul de timp necesar pentru a stabili

conxiunile acestea nu este neglijabil acest lucru poate mari timpul total pentru transferul applet-ului si

fisierelor sale pana la durate inacceptabile .

Solutia acestei probleme este crearea unei arhive Java , adica un fisier JAR . O arhiva Java reprezinta o

colectie de clase Java si alte fisiere , impachetate intr-un singur fisier . Folosind o arhiva Java browser-

ului ii este suficienta o singura conexiune la serverul web . Reducand numarul de fisiere transferate de

pe server applet-ul poate fi incarcat si rulat mai rapid . Arhivele Java pot fi si comprimate , scazandu-le

astfel dimensiunea si micsorandu-se timpul de transfer – dar in schimb va dura ceva mai mult din

partea browser-ului decomprimarea inainte de rulare .

Pentru a crea arhive JAR putem folosi utilitarul JAVA denumit jar , care poate impacheta sau

despacheta fisierele in/din arhive Java . Urmatoarea comanda impacheteaza toate clasele si imaginile

.gif dintr-un director intr-o singura arhiva Java , denumita Animat.jar :

jar cf Animat.jar *.class *.gif

Argumentul cf specifica doua optiuni in linie de comanda care sunt folosite de programul jar .

Optiunea c indica faptul ca arhiva Java trebuie creata iar f arata ca unul dintre urmatoarele argumente

din linia de comanda reprezinta numele arhivei .

- 72 -

Page 73: Programare Java

Putem , de asemenea , adauga intr-o arhiva Java alte fisiere folosind comanda :

jar cf Smiley.jar ShowSmiley.class ShowSmiley.html spinhead.gif

Ruland utilitarul jar fara nici un argument vom obtine list a de optiuni care pot fi folosite .

Dupa ce am creat arhiva Java , in eticheta <applet> se foloseste atributul ARCHIVE pentru a indica

locul unde se gaseste arhiva . Putem folosi arhiva Java in felul urmator :

<applet code=ShowSmiley.class archive=Smiley.jar width=45 height=42>

</applet>

Aceasta eticheta specifica faptul ca arhiva numita Smiley.jar contine fisierele folosite de applet .

Browser-ele si utilitarele de navigare care suporta fisiere JAR stiu sa caute in interiorul arhivelor

fisierele necesare pe timpul rularii applet-ului .

OBS : cu toate ca o arhiva Java poate contine fisiere clasa atributul ARCHIVE nu presupune

eliminarea atributului CODE . Pentru a o incarca browser-ul trebuie totusi sa stie numele clasei

principale a applet-ului .

ALTE FORMATE DE ARHIVARE

Versiunile curente ale celor mai raspandite browser-e – ale firmelor Microsoft si Netscape – suporta pe

langa arhive JAR si formate recunoscute ca ZIP sau CAB .

Exemplul de mai jos foloseste o arhiva ZIP :

<applet code=AppletulMeu.class archive=utile.zip width=100 height=100>

</applet>

Microsoft a introdus un utilitar CABarc care realizeaza arhive in formatul CAB . Pentru a specifica

aceasta arhiva in codul HTML se foloseste eticheta <param> impreuna cu un parametru numit

cabbase , valoarea acestuia fiind numele fisierului cab . Iata un exemplu :

<applet code=AppletulMeu.class width=100 height=100>

<param name=cabbase value=AppletulMeu.cab>

</applet>

Ca si atributul ARCHIVE , parametrul cabbase va fi ignorat de browser-ele web care nu suporta

folosirea sa .

- 73 -

Page 74: Programare Java

Programare Java

Curs – 7

UTILIZAREA CLASELOR LEGATE DE GRAFICA, FONTURI SI CULORI

CLASA GRAPHICS

Un applet foloseste metoda drawString() pentru a desena text. Fontul si culoarea textului au fost deja alese anterior desenarii

textului.

Textul nu este singurul lucru pe care il putem desena in fereastra appletului; tot aici putem insera linii , cercuri , ovaluri ,

dreptunghiuri si alte forme geometrice.

Majoritatea operatiilor de desenare sunt metode definite in clasa Graphics. Intr-un applet nu este nevoie sa cream un obiect

Graphics pentru a putea desena ceva - unul dintre argumentele metodei paint() este un obiect Graphics - acesta reprezinta

fereastra appletului iar metodele sale sunt folosite pentru a desena in applet.

Clasa Graphics este parte a pachetului java.awt , deci toate appleturile care deseneaza ceva trebuie sa foloseasca instructiunea

import pentru a putea folosi aceasta clasa .

In exemplul urmator avem un applet care foloseste drawString() pentru a afisa un text :

import java.awt.Graphics;

public class Harta extends java.applet.Applet {

public void paint(Graphics ecran) {

ecran.drawString("Harta",185,75);

}

}

Pentru a insera acest applet trebuie sa cream un fisier HTML ca cel de mai jos :

<body bgcolor=c4c4c4>

<div align=center>

<applet code="Harta.class" height=350 width=350>

</applet>

</div>

</body>

Toate comenzile de baza de desenare sunt metode ale clasei Graphics , apelate din cadrul metodei paint() . Acesta este locul

ideal unde se pot desfasura toate operatiile de desenare deoarece metoda este apelata automat oricand este nevoie de

reimprospatarea ferestrei appletului . Daca fereastra altui program se suprapune peste applet si acesta trebuie redesenat ,

introducerea tuturor operatiilor de desenare in metoda paint() asigura ca nici o parte a ferestrei nu va fi eventual stricata .

DESENAREA SI UMPLEREA

Pentru majoritatea formelor pe care putem sa le desenam intr-un applet exista doua tipuri de metode : de desenare - care

deseneaza conturul formei , si de umplere - care umplu forma cu culoarea curenta . In fiecare tip de metoda , conturul

obiectului este desenat si el cu culoarea curenta .

LINIILE

Metoda drawLine() este folosita pentru a desena o linie intre doua puncte . Metoda primeste patru argumente : coordonatele x

, y ale punctului de inceput si coordonatele x , y ale punctului final :

drawLine (x1 , y1 , x2 , y2 );

Aceasta metoda deseneaza linia cu grosimea de un pixel .

Adaugarea urmatoarei linii de cod in appletul nostru anterior - Harta.java - are ca rezultat trasarea unei linii intre coordonatele

(185,80) si (222,80) :

ecran.drawLine(185,80,222,80);

DREPTUNGHIURI

- 74 -

Page 75: Programare Java

Clasa Graphics contine metode pentru doua tipuri de dreptunghiuri : normale si cu colturile rotunjite .

Ambele tipuri de dreptunghiuri pot fi desenate sub forma de contur sau umplute cu culoarea curenta .

Pentru a desena un dreptunghi normal se foloseste metoda drawRect() pentru contururi si fillRect() pentru forme umplute .

Ambele metode preiau patru argumente :

- coordonatele x si y ale coltului din stanga-sus al dreptunghiului

- latimea dreptunghiului

- inaltimea dreptunghiului

Adaugam acum urmatoarea linie la appletul nostru :

ecran.drawRect(2,2,345,345);

Aceasta instructiune adauga un contur dreptunghiular aproape de marginile ferestrei appletului . Daca am fi folosit metoda

fillRect() toata zona appletului ar fi fost acoperita de un dreptunghi plin de culoare , fapt ce ar fi dus la acoperirea textului .

Dreptunghiurile cu colturile rotunjite se deseneaza cu ajutorul metodelor drawRoundRect() si fillRoundRect() . Acestea

preiau aceleasi patru argumente pentru dreptunghiuri normale plus inca doua argumente suplimentare . Aceste doua

argumente definesc latimea si inaltime zonei unde se rotunjesc colturile . Cu cat aceasta zona este mai mare cu atat mai

rotunjite sunt colturile . Daca aceste argumente sunt suficient de mari dreptunghiul poate deveni chiar un cerc sau un oval .

Pentru a exemplifica si aceasta comanda sa adaugam o noua linie in appletul nostru :

ecran.drawRoundRect(182,61,43,24,10,8);

Rezultatul acestei instructiuni este desenarea unui dreptunghi rotunjit cu o latime de 43 de pixeli si o inaltime de 24 de pixeli .

Zona dreptunghiulara pentru fiecare colt rotunjit este de 10 pixeli latime si 8 inaltime .

POLIGOANE

Poligoanele se realizeaza cu metodele drawPolygon() si fillPolygon() .

Pentru a realiza desenarea avem nevoie de coordonatele x si y ale fiecarui punct care defineste colturile poligonului .

Poligoanele pot fi definite ca o serie de linii interconectate .

Putem specifica aceste coordonate in doua moduri :

- ca o pereche de tablouri cu intregi , dintre care unul pastreaza valorile coordonatei x si celalalt pastreaza toate

valorile coordonatei y

- ca un obiect Polygon creat folosind un tablou cu valori intregi ale coordonatei x si un tablou cu valori intregi ale

coordonatei y

A doua metoda este mai flexibila deoarece permite adaugarea individuala a punctelor unui poligon inainte de desenarea sa .

In afara de coordonatele x si y trebuie sa specificam si numarul de puncte al poligonului . Nu se pot specifica mai multe

coordonate x , y decat numarul de puncte si nici invers . In oricare din aceste cazuri compilatorul va semnala eroare .

pentru a crea un obiect Poligon primul pas este crearea unui poligon gol , printr-o instructiune new :

Polygon polig=new Polygon();

Putem crea un poligon si pornind de la un set de puncte , folosind tablouri cu valori intregi . Aceasta necesita un apel catre

constructorul Polygon(int[],int[],int[]) , unde se specifica tabloul cu valori pentru coordonata x , tabloul cu valori pentru

coordonata y si numarul de puncte ( colturi ) :

int x[]={10,20,30,40,50};

int y[]={15,25,35,45,55};

int puncte=x.length;

Polygon polig=new Polygon(x,y,puncte);

Dupa crearea obiectului Polygon se pot adauga puncte folosind metoda addPoint() . Aceasta preia ca argumente coordonatele

x si y si adauga punctul in poligon :

polig.addPoint(60,65);

Atunci cand obiectul poligon are toate punctele el poate fi desenat folosind una dintre metodele drawPoliyon() sau

fillPolygon() . Aceste metode au drept unic argument obiectul Polygon :

- 75 -

Page 76: Programare Java

ecran.drawPoligon(polig);

Metoda fillPolygon() inchide automat forma poligonala fara a mai fi nevoie de specificarea coordonatei finale identice cu cea

initiala.

Metoda drawPolygon() inchide si ea automat poligonul , daca dorim un poligon deschis folosim o alta instructiune :

drawPolyline().

Pentru a desena un poligon in appletul nostru adaugam liniile de cod :

int x[]={10,234,253,261,344,295,259,205,211,195,191,120,94,81,12,10};

int y[]={12,15,25,71,209,278,310,274,188,171,174,118,56,68,49,37,12};

int pct=x.length;

Polygon polig=new Polygon(x,y,pct);

ecran.drawPolygon(polig);

Clasa Polygon face parte din pachetul java.awt , deci acesta trebuie importat prin adaugarea instructiunii urmatoare la

inceputul appletului :

import java.awt.Polygon;

OVALE

Metodele drawOval() si fillOval sunt utilizate pentru a desena cercuri si ovale .

Metodele preiau patru argumente :

- coordonatele x si y ale ovalului

- latime si inaltime ovalului - care in cazul cercurilor iau valori egale

Deoarece ovalele nu au colturi asa ca respectivele coordonate x si y pe care le primesc aceste metode se refera de fapt la

punctul din stanga-sus al zonei in care va fi desenat ovalul , aflandu-se de fapt la stanga si mai sus decat forma geometrica

propriu-zisa .

In appletul nostru sa adaugam urmatoarele instructiuni :

ecran.fillOval(235,140,15,15);

ecran.fillOval(225,130,15,15);

ecran.fillOval(245,130,15,15);

Acestea sunt metode de umplere iar rezultatul lor vor fi trei cercuri colorate in culoarea curenta .

ARCE DE CERC

Desenarea arcelor de cerc este o operatie ceva mai complexa ; un arc este parte a unui oval , fiind implementat de fapt ca

parte a unui oval partial desenat .

Arcele sunt folosite cu ajutorul metodelor drawArc() si fillArc() , care preiau sase argumente :

- coordonatele x si y ale ovalului din care face parte arcul

- latime si inaltime acestui oval

- unghiul de unde incepe trasarea arcului

- numarul de grade al arcului

Primele patru argumente sunt identice cu cele din cazul ovalelor si au acelasi rol ca si in acel caz .

Unghiul de inceput al arcului ia valori intre 0 si 359 de grade si creste in sens trigonometric ( invers acelor de ceas ) . Pe un

cerc de forma unui ceas putem vedea 0 grade in dreptul orei 3 , 90 de grade la ora 12 , 180 de grade la ora 9 si 270 de grade la

ora 6 .

Numarul de grade pe care se intinde arcul ia valori de la 0 la 359 tot in sens contrar acelor de ceas sau de la 0 la -359 in sensul

acelor de ceas .

Arcele umplute sunt desenate ca si cand ar fi felii dar , in loc sa se uneasca direct cele doua puncte terminale acestea sunt

unite prin intermediul centrului formei eliptice ( ovalului ) .

In continuare avem un exemplu de metoda pentru desenarea arcelor :

ecran.drawArc(20,25,315,150,5,-190);

- 76 -

Page 77: Programare Java

Aceasta instructiune deseneaza un arc oval cu coordonatele 20 si 25 , o latime de 315 pixeli si o inaltime de 150 pixeli . Arcul

incepe la valoarea de 5 grade si se intinde pe o distanta de 190 de grade in sensul acelor de ceas .

Sa adaugam in appletul nostru o serie de arcuri cu caracteristicile urmatoare :

- ovalul fiecarui arc are o latime si o inaltime egale cu 10 pixeli , deci ovalul devine de fapt cerc

- fiecare arc va incepe la 0 grade si va merge 180 de grade in sensul acelor de ceas desenand un semicerc

Coordonatele x si y ale arcului se vor modifica folosindu-se doua cicluri for :

for(int ax=50;ax<150;ax+=10)

for (int ay=120;ay<320;ay+=10)

ecran.drawArc(ax,ay,10,10,0,-180);

COPIEREA SI STERGEREA

Clasa Graphics contine si cateva functii de gen cut&paste , aplicabile ferestrei appletului :

- metoda copyArea() - care copiaza o regiune dreptunghiulara a ferestrei intr-o alta regiune a ferestrei

- metoda clearRect() - care decupeaza o regiune dreptunghiulara din fereastra appletului

Metoda copyArea() preia sase argumente :

- coordonatele x si y ale regiunii de copiat

- latimea si inaltimea regiunii

- distanta pe orizontala si verticala - in pixeli - cu care se deplaseaza copia fata de regiunea initiala , inainte de afisare

Urmatoarea instructiune copiaza o regiune de 100 pe 100 de pixeli intr-o zona aflata cu 50 de pixeli mai la dreapta si cu 25 de

pixeli mai jos :

ecran.copyArea(0,0,100,100,50,25);

Metoda clearRect() preia aceleasi patru argumente ca si metoda drawRect() sau fillRect() , umpland regiunea dreptunghiulara

astfel creata cu culoarea curenta de fundal a appletului .

Daca dorim sa stergem intreaga fereastra applet putem determina mai intai dimensiunea ferestrei folosind metoda size() .

Aceasta returneaza un obiect Dimension , care poseda variabilele width si height ; acestea reprezinta dimensiunile appletului .

In continuare avem si un exemplu de utilizare a metodei :

ecran.clearRect(0,0,size().width,size().height);

In versiunile mai noi de Java compilatorul ne va anunta ca functia size() este depreciata , ea putand fi inlocuita cu getSize() ,

care functioneaza identic .

TEXT SI FONTURI

Obiectele clasei java.awt.Font sunt folosite pentru a putea utiliza metoda drawString() cu diferite tipuri de caractere .

Obiectele Font contin numele , stilul si dimensiunea in puncte a unui font . O alta clasa , FontMetrics , ofera metode pentru

determinarea dimensiunilor si a caracterelor afisabile cu un anumit font , care pot fi folosite pentru formatarea sau centrarea

textului .

CREAREA OBIECTELOR FONT

Un astfel de obiect se creaza prin apelarea constructorului sau cu trei argumente :

- numele fontului

- stilul fontului

- dimensiunea in puncte a fontului

- 77 -

Page 78: Programare Java

Numele poate fi denumirea unui font specifc - de exemplu Arial sau Garamond - care va putea fi folosit daca este disponibil

pe sistemul unde ruleaza programul . Exista si alte nume care pot fi folosite pentru selectarea fonturilor interne ale Java :

TimesRoman , Helvetica , Courier , Dialog si DialogInput .

In versiunile mai noi de Java numele fonturilor TimesRoman , Helvetica si Courier trebuie inlocuite cu serif,sanserif si

monospaced .

Stilul de font poate avea trei valori , apelate folosind constantele Font.PLAIN , Font.BOLD si Font.ITALIC . Aceste

constante sunt intregi si pot fi insumate pentru a obtine o combinatie de efecte .

Dimensiunea fontului este data in puncte , ca in exemplul de mai jos care implementeaza un font Dialog de 24 de puncte , cu

caractere bold si italice :

Font f=new Font("Dialog",Font.BOLD+Font.ITALIC,24);

DESENAREA CARACTERELOR SI SIRURILOR

Pentru a stabili fontul folosit in applet se utilizeaza metoda setFont() a clasei Graphics , impreuna cu un obiect Font :

ecran.setFont(f);

Textul poate fi afisat intr-o fereastra applet cu ajutorul lui drawString() . Aceasta functie foloseste fontul curent selectat - sau

cel implicit .

Urmatoarea metoda paint() creaza un nou obiect Font , stabileste fontul curent la acest obiect si afiseaza un text la

coordonatele 10 , 100 :

public void paint(Graphics ecran) {

Font f=new Font("TimesRoman",Font.PLAIN,72);

ecran.setFont(f);

ecran.drawString("Text de afisat in applet",10,100);

Valoarea x reprezinta locul de inceput al marginii din stanga a textului iar y este valoarea la care se afiseaza linia de baza a

sirului de text .

AFLAREA DE INFORMATII DESPRE FONT

Clasa FontMetrics poate fi folosita pentru a afla informatii detaliate despre fontul curent , cum ar fi latimea sau inaltimea

caracterelor pe care le poate afisa .

Pentru a folosi metodele acestei clase , trebuie mai intai creat un obiect FontMetrics prin metoda getFontMetrics() . Aceasta

metoda primeste un singur argument : un obiect Font .

Un obiect FontMetrics poate apela mai multe metode :

- stringWidth(String) - intoarce latimea totala a sirului , in pixeli

- charWidth(char) - intoarce latimea unui caracter dat

- getHeight() - intoarce inaltimea totala a fontului

In continuare avem un exemplu de utilizare a metodelor acestei clase FontMetrics :

import java.awt.Font;

import java.awt.Graphics;

import java.awt.FontMetrics;

public class SoLong extends java.applet.Applet {

public void paint(Graphics ecran) {

Font f=new Font("Courier",Font.BOLD,18);

FontMetrics fm=getFontMetrics(f);

ecran.setFont(f);

String s="La revedere.";

int x=(size().width-fm.stringWidth(s))/2;

int y=size().height/2;

ecran.drawString(s,x,y);

}

}

- 78 -

Page 79: Programare Java

Determinarea dimensiunii ferestrei appletului in cadrul sau este preferabila metodei de definire a unei dimensiuni statice in

applet , deoarece este mai flexibila . Putem modifica codul sursa HTML al appletului in pagina web fara a modifica si

programul nostru , acesta functionand in continuare corect .

CULORI

Clasele Color si ColorSpace din pachetul java.awt pot fi folosite pentru a aduce culoare in appleturi si aplicatii . Cu ajutorul

acestor clase putem stabili culorile curente folosite in operatiile de desenare , ca si culoarea de fundal pentru un applet sau alte

ferestre . De asemenea putem translata o culoare dintr-un sistem de descriere in altul .

In mod prestabilit Java foloseste culorile conform sistemului RGB . In acest sistem o culoare este descrisa prin cantitatea de

rosu , verde si albastru pe care o contine ( red - green - blue ) . Fiecare dintre cele trei componente poate fi reprezentata cu un

intreg din gama 0 - 255 . Combinatia 0,0,0 reprezinta negru . Putem specifica o combinatie RGB si prin trei valori in virgula

mobila , in gama 0 - 1 .

Un alt sistem de culori - sau spatiu de culori - este CYMK , care specifica o culoare prin cantitatea de azuriu ( cyan ) , mov (

magenta ) , galben ( yellow ) si negru ( black ) .

Java2 suporta folosirea oricarui tip de spatiu de culori atata timp cat folosim un obiect ColorSystem care defineste sistemul

respectiv de descriere a culorilor .

Reprezentarea interna a culorilor in Java folosind RGB este spatiul de culoare utilizat in program ; dispozitivele de iesire pot

avea si ele propriile spatii de culoare .

In practica o culoare definita RGB poate sa apara usor diferit pe un alt dispozitiv de iesire decat monitorul . Pentru un control

mai bun asupra culorii putem folosi ColorSpace sau alte clase din pachetul java.awt.color .

FOLOSIREA OBIECTELOR COLOR

Pentru a stabili culoarea curenta de desenare trebuie sa cream un obiect Color care sa reprezinte culoarea dorita , fie sa

folosim una dintre culorile standard existente in clasa .

Pentru a crea o culoare avem doua metode de apelare a metodei constructor Color :

- folosirea a trei intregi pentru valorile RGB dorite

- folosirea a trei numere reale intre 0 si 1 care sa reprezinte acelasi lucru

Putem defini valoarea RGB a culorii in urmatoarele moduri :

Color c1=new Color(0.807F,1F,0F);

Color c2=new Color(255,204,102);

TESTAREA SI STABILIREA CULORILOR CURENTE

Culoarea curenta pentru desenare este desemnata folosind metoda setColor() a clasei Graphics . Aceasta metoda trebuie

apelata pentru obiectul Graphics care reprezinta zona in care desenam . Intr-un applet acest obiect este cel transmis metodei

paint() .

O modalitate de a stabili culoarea de desenare este folosirea uneia dintre culorile standard disponibile ca variabila de clasa in

clasa Color .

Aceste culori folosesc urmatoarele variabile Color :

- black , blue , cyan , darkGray , gray , green , lightGray , magenta , orange , pink , red , white , yellow .

Urmatoarea instructiune stabileste culoarea curenta pentru obiectul ecran folosind una dintre variabilele standard de clasa :

ecran.setColor(Color.pink);

Daca am creat un obiect Color el poate fi utilizat in mod asemanator :

Color culoare=new Color(255,204,102);

ecran.setColor(culoare);

Din acest moment toate operatiile de desenare vor folosi aceasta culoare .

- 79 -

Page 80: Programare Java

Putem stabili culoarea de fundal intr-o fereastra applet folosind metodele setBackground() si setForeground() . Acestea sunt

mostenite de clasa Applet de launa dintre superclasele sale asa incat toate appleturile create vor mosteni si ele aceste metode .

Metoda setBackground() seteaza culoare de fundal primind ca argument un obiect Color .

Metoda setForeground() functioneaza la fel ca metoda setColor , dar schimba culoarea unei componente a interfetei grafice -

ca de exemplu un buton sau o fereastra . Datorita faptului ca un applet este o fereastra putem folosi setForeground() in metoda

init() pentru a seta culorile pentru operatiile de desenare . Aceasta culoare va fi folosita pana la alegerea unei alte culori cu

una dintre metodele setForeground() sau setColor() .

Daca vrem sa aflam care este culoarea curenta putem folosi metoda getColor() pentru un obiect grafic , respectiv una dintre

metodele getForeground() sau getBackground() pentru clasa Applet .

Urmatoarea instructiune stabileste culoarea curenta pentru ecran - un obiect Graphics - ca fiind aceeasi cu fundalul appletului

:

ecran.setColor(getBackground());

OPERATII GRAFICE FOLOSIND JAVA2D

Una dintre imbunatatirile aduse de Java2 este Java2D , un set de clase pentru crearea unor imagini si texte bidimensionale de

inalta calitate . Clasele Java2D extind facilitatile claselor grafice din java.awt , cum sunt cele pe care le-am vazut in paginile

anterioare . Ele nu inlocuiesc clasele existente ci doar aduc posibilitati noi .

Functiile Java2D contin printre altele :

- metode speciale de umplere cu degradeuri si texturi

- tuse care definesc grosime si stilul desenului

- posibilitati de netezire a marginilor obiectelor desenate ( anti-aliasing )

SPATIUL DE COORDONATE AL UTILIZATORULUI SI CEL AL DISPOZITIVULUI

Unul dintre conceptele din Java2D este diferentierea intre spatiul de coordonate al dispozitivului de iesire si spatiul de

coordonate la care ne referim cand desenam .

Pentru toate operatiile de desenare de pana acum singurul spatiu de coordonate folosit era cel al dispozitivului . Se specificau

coordonatele x si y ale unei suprafete de iesire - ca fereastra Applet - si aceste coordonate erau folosite pentru a desena linii ,

text si altele .

Java2D are nevoie de un al doilea spatiu de coordonate , la care facem referire atunci cand cream si desenam un obiect .

Acesta este numit spatiu de coordonate al utilizatorului .

Inainte de a folosi operatii de desenare Java2D in program , spatiul dispozitivului si cel al utilizatorului au punctul de

coordonate 0 , 0 in acelasi loc , coltul din stanga-sus al zonei de desenare .

Coordonata 0,0 a spatiului utilizator se poate deplasa ca urmare a unei operatii de desenare 2D . Chiar si axele x , y se pot

modifica drept urmare a unei rotiri 2D .

CONVERSIA LA UN OBIECT GRAPHICS2D

Operatiile de desenare de pana acum sunt apelate pentru obiecte Graphics ce reprezinta zona in care desenam ; pentru Java2D

acest obiect trebuie folosit pentru a crea un nou obiect Graphics2D , ca in urmatoarea metoda paint() :

public void paint(Graphics ecran) {

Graphics2D ecran2D=(Graphics)ecran;

}

Obiectul ecran2D din exemplul nostru a fost produs printr-o conversie cast . El este obiectul ecran , convertit dintr-o clasa in

alta .

Toate operatiile grafice Java2D trebuie apelate pentru un obiect Graphics2D ; aceasta clasa , Graphics2D , face si ea parte din

java.awt .

SPECIFICAREA ATRIBUTELOR DE RANDARE

Desenele care nu sunt 2D pot selecta un singur atribut : culoarea . 2D ofera o gama larga de atribute de culoare , grosimea

liniei , modelul de umplere , transparenta si altele .

- 80 -

Page 81: Programare Java

CULORI 2D

Culorile sunt specificate folosind metoda setColor() , care funtioneaza la fel cu metoda Graphics cu acelasi nume - diferenta

constand in obiectul argument care acum este de tip Graphics2D .

MODELE DE UMPLERE

Texturile sau modelele de umplere , definesc modul cum este umplut un obiect . In Java2D putem folosi o culoare solida , un

degrade , o textura sau un model oarecare.

Un model de umplere este definit prin folosirea metodei setPaint() a clasei Graphics2D , avand ca argument un obiect Paint .

Interfata Paint este implementata de fiecare clasa care poate juca rolul unui model de umplere - ca de exemplu GradientPaint ,

TexturePaint sau Color .

O umplere in degrade inseamna o trecere gradata de la o culoare la alta intre doua coordonate . Aceasta deplasare a culorii

poate aparea o singura data intre cele doua coordonate , caz in care se numeste aciclica sau poate apare in mod repetat , caz in

care se numeste ciclica .

Punctele de coordonate dintr-un degrade nu se refera direct la punctele obiectului Graphics2D pe care desenam . De fapt ele

se refera la spatiul utilizator si se pot afla chiar in afara obiectului ce urmeaza a fi umplut cu respectivul degrade .

Un apel catre constructorul GradientPaint este de forma :

GradientPaint(x1,y1,culoare1,x2,y2,culoare2);

Punctul x1,y1 este punctul de unde incepe culoare culoare1 iar x2,y2 este punctul unde se termina trecerea la culoare2 .

Pentru a implementa un degrede ciclic introducem un argument suplimentar :

GradientPaint(x1,y1,culoare1,x2,y2,culoare2,true);

Ultimul argument este o valoare booleana care are valoarea true pentru degradeul ciclic ; argumentul false poate fi folosit

pentru varianta aciclica sau poate fi omis .

Dupa ce am definit un obiect GradientPaint il vom declara atribut curent de desenare cu setPaint() :

GradientPaint model=new GradientPaint(0f,0f,Color.white,100f,45f,Color.blue);

ecran2D.setPaint(model);

Toate operatiile de desenare care vor urma pentru obiectul ecran2D vor folosi acest model de umplere .

STABILIREA UNEI TUSE DE DESEN

Liniile desenate in operatiile non-Java2D au grosimea standard de 1 pixel . Java2D da posibilitatea de a modifica grosimea

liniei de desenare cu metoda setStroke() pentru un obiect BasicStroke .

Un constructor BasicStrole simplu preia trei argumente :

- o valoare float pentru grosimea liniei , valoarea implicita fiind 1.0

- o valoare int care determina stilul terminatiei liniei

- o valoare int care determina stilul imbinarii intre doua segmente de linie

Stilurile de terminatie ( endcap ) sunt aplicate liniilor care nu se conecteaza la alte linii . Stilurile de imbinare ( juncture ) sunt

aplicate capetelor de linie care se conecteaza la alte linii .

Stilurile posibile pentru terminatii sunt CAP_BUTT ( fara terminatie ) , CAP_ROUND ( pentru terminatii circulare ) si

CAP_SQUARE ( pentru terminatii rectangulare)

Diferenta intre primul si ultimul stil este foarte mica , o linie cu CAP_SQUARE fiind mai lunga , datorita terminatiei de

forma patrata .

Stilurile de imbinare sunt JOIN_MITER ( pentru imbinarea prin prelungirea muchiilor exterioare ) , JOIN_ROUND ( pentru

imbinarea rotunjita ) si JOIN_BEVEL ( pentru o imbinare tesita ) .

Exemplul de mai jos creaza un obiect BasicStroke si il stabilesc drept stil de tusa curent :

- 81 -

Page 82: Programare Java

BasicStroke creion=BasicStroke(2.0f,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND);

ecran2D.setStroke(creion);

Efectul liniilor de mai sus este o tusa de 2 pixeli , terminatii netede ale segmentelor si colturi de imbinare rotunjite .

CREAREA OBIECTELOR CE VOR FI DESENATE

Desenarea obiectelor in Java2D se face prin definirea lor ca forme geometrice , folosind clasele pachetului java.awt.geom .

Putem desena toate formele intalnite pana acum - linii , dreptunghiuri , ovale , arce si poligoane .

Clasa Graphics2D nu poseda metode diferite pentru desenarea fiecareia dintre forme . In schimb se defineste mai intai forma

dorita si apoi se foloseste ca argument pentru una dintre metodele fill() sau draw() .

LINII

Se creaza folosind clasa Line2d.Float . Aceasta clasa preia patru argumente : coordonetele x , y ale unui capat de segment si

coordonatele x , y ale celuilalt capat :

Line2D.Float ln=new Line2D.Float(60f,5f,13f,28f);

Aceasta instructiune creeaza o linie intre punctele 60,5 si 13,28 . Mentionam utilizarea literei f pentru specificarea tipului

float pentru argumente .

DREPTUNGHIURI

Acestea sunt create folosind clasele Rectangle2D.Float sau Rectangle2D.Double . Diferenta intre cele doua este tipul

argumentelor .

Rectangle2D.Float primeste patru argumente : coordonatele x , y , latimea si inaltimea :

Rectangle2D.Float dr=new Rectangle2D.Float(10f,13f,40f,20f);

ELIPSE

Obiectele ovale sunt numite in Java2D elipse si pot fi create cu clasa Ellipse2D.Float . Este nevoie de patru argumente :

coordonatele x , y , latimea si inaltimea .

Instructiunea de mai jos creaza o elipsa la coordonata 113,25 cu o latime de 22 pixeli si o inaltime de 40 pixeli :

Ellipse2D.Float el=new Ellipse2D.Float(113,25,22,40);

ARCE

Acestea sunt create prin clasa Arc2D.Float . Sunt create asemanator cu versiunea lor non-2D dar cu o diferenta : putem stabili

modul de inchidere .

Arc2D.Float primeste sapte argumente . Primele patru se refera la elipsa din care face parte arcul : coordonatele x , y , latimea

si inaltimea . Ultimele trei se refera la unghiul de unde incepe desenarea , numarul de grade pe care se intinde si un intreg care

stabileste modul de inchidere .

Exista o deosebire fata de arcele non-2D : numarul de grade pe care se intinde arcul 2D este specificat ca avand sensul pozitiv

in sensul acelor de ceas .

Ultimul argument foloseste una dintre variabilele de clasa : Arc2D.OPEN ( pentru arc dechis ) , Arc2D.CHORD ( pentru un

arc ale carui capete sunt unite printr-o linie dreapta ) si Arc2D.PIE ( pentru un arc cu capetele unite prin intermediul centrului

elipsei . Mai trebuie mentionat ca stilul de inchidere Arc2D.OPEN nu se aplica arcelor umplute ; un astfel de arc umplut va fi

automat inchis cu stilul Arc2D.CHORD .

Instructiunile de mai jos creaza un arc dintr-o elipsa cu coordonatele 27,22, 42 de pixeli latime si 30 inaltime . Arcul incepe la

33 de grade , se intinde pe 90 de grade in sensul acelor de ceas si va fi inchis prin intermediul centrului elipsei :

Arc2D.Float arc=new Arc2D.Float(27,22,42,30,33,90,Arc2D.PIE);

- 82 -

Page 83: Programare Java

POLIGOANE

Acestea sunt create in Java2D prin deplasarile dintr-un punct al poligonului in altul . Un poligon poate fi format din linii

drepte , curbe patratice sau curbe Bezier .

Deplasarile necesare pentru crearea poligonului sunt definite in obiectul GeneralPath , care apartine pachetului java.awt.geom

.

Un obiect GeneralPath poate fi creat fara argumente :

GeneralPath polig=new GeneralPath();

Metoda moveTo() a clasei GeneralPath este folosita pentru a crea primul punct al poligonului . Urmatoarea instructiune poate

fi folosita pentru a incepe poligonul de la coordonatele 5,0 :

polig.moveTo(5f,0f);

Dupa crearea primului punct , metoda lineTo() se foloseste pentru crearea unei linii care incepe din punctul curent si se

termina intr-un nou punct . Metoda primeste doua argumente : coordonatele x si y ale noului punct .

Urmatoarele instructiuni creaza trei linii pentru obiectul polig :

polig.lineTo(205f,0f);

polig.lineTo(205f,90f);

polig.lineTo(5f,90f);

Metodele lineTo() si moveTo() primesc ca argumente ale coordonatelor valori float() . Daca vrem sa inchidem un poligon se

poate folosi metoda closePath() fara nici un argument :

polig.closePath();

Aceasta metoda inchide un poligon prin conectarea punctului curent cu punctul specificat in cel mai recent apel de metoda

moveTo() . Putem inchide poligonul si fara aceasta metoda , prin folosirea metodei LineTo() care conecteaza punctul curent

cu punctulinitial al poligonului .

O data creata forma poligonala ea poate fi reprezentata ( desenata ) ca orice alt obiect , cu metodele fill() sau draw() .

DESENAREA OBIECTELOR

Toate obiectele pe care le vom desena in continuare folosesc metode ale clasei Graphics2D : draw() si fill() . Aceste metode

primesc ca unic argument obiectul ce trebuie desenat .

Sirurile sunt desenate in Java2D tot cu drawString() . Aceasta preia trei argumente : obiectul String si coordonatele x si y - cu

mentiunea ca aceste coordonate sunt de tip float , ca la toate coordonatele din Java2D .

Sa incheiem problematica abordata in acest curs cu un exemplu de desenare 2D :

import java.awt.*;

import java.awt.geom.*;

public class Harta2D extends java.applet.Applet {

public void paint(Graphics ecran) {

Graphics2D ecran2D=(Graphics2D)ecran;

setBackground(Color.blue);

//Desenare valuri

ecran2D.setColor(Color.white);

BasicStroke creion=new BasicStroke(2F,BasicStroke.CAP_BUTT,BasicStroke.JOIN_ROUND);

ecran2D.setStroke(creion);

for (int ax=10;ax<340;ax+=10)

for (int ay=30;ay<340;ay+=10){

Arc2D.Float val=new Arc2D.Float(ax,ay,10,10,0,-180,Arc2D.OPEN);

ecran2D.draw(val);

}

//Desenare harta

GradientPaint degrade=new GradientPaint(0F,0F,Color.green,50F,50F,Color.orange,true);

ecran2D.setPaint(degrade);

GeneralPath f1=new GeneralPath();

- 83 -

Page 84: Programare Java

f1.moveTo(10F,12F);

f1.lineTo(234F,15F);

f1.lineTo(253F,25F);

f1.lineTo(261F,71F);

f1.lineTo(344F,209F);

f1.lineTo(336F,278F);

f1.lineTo(295F,310F);

f1.lineTo(259F,274F);

f1.lineTo(205F,188F);

f1.lineTo(211F,171F);

f1.lineTo(195F,174F);

f1.lineTo(191F,118F);

f1.lineTo(120F,56F);

f1.lineTo(94F,68F);

f1.lineTo(81F,49F);

f1.lineTo(12F,37F);

f1.closePath();

ecran2D.fill(f1);

//Desenare elipse

ecran2D.setColor(Color.black);

BasicStroke creion2=new BasicStroke();

ecran2D.setStroke(creion2);

Ellipse2D.Float e1=new Ellipse2D.Float(235,140,15,15);

Ellipse2D.Float e2=new Ellipse2D.Float(225,130,15,15);

Ellipse2D.Float e3=new Ellipse2D.Float(245,130,15,15);

ecran2D.fill(e1);

ecran2D.fill(e2);

ecran2D.fill(e3);

}

}

- 84 -

Page 85: Programare Java

Programare Java

Curs - 8

FOLOSIREA IMAGINILOR, ANIMATIEI SI SUNETULUI

Animatia in Java se realizeaza prin folosirea AWT - mai precis a unor componente ale sale . Putem crea animatie si

folosind instructiunile de desenare invatate in cursurile anterioare dar la acest moment vom trece la folosirea unor imagini

deja create - sub forma de fisiere grafice cu diverse extensii .

Avem de facut practic doi pasi conceptuali pentru a realiza o animatie :

- desenarea

- comandarea sistemului de ferestre pentru a afisa desenul realizat anterior

Daca repetam acesti pasi se reuseste crearea teoretica a unei miscari .

DESENAREA SI REIMPROSPATAREA DESENULUI

In mod normal metoda paint() care deseneaza fereastra unui applet este apelata automat de Java ; pentru un control mai bun

al afisarii avem si posibilitatea de a apela chiar noi redesenarea prin metoda repaint() .

Deci pentru a modifica o fereastra applet trebuie sa desenam ceva apoi sa apelam repaint() pentru a vedea rezultatul .

Operatiile acestea de desenare nu vor fi create in metoda paint() deoarece s-ar executa toate direct de la inceputul afisarii

ferestrei .

PORNIREA SI OPRIREA EXECUTIEI APPLETULUI

Pentru aceste lucruri exista metodele start() si stop() ale clasei Applet . Aceste metode sunt vide si va trebui sa le

suprascriem atunci cand incepem sau finalizam programul . Desi la desenarea unor lucruri simple aceste metode nu erau

necesare , pentru animatie situatia se schimba .

CONTROLUL PRIN FIRE DE EXECUTIE

Firele de executie , numite si thread-uri , sunt un lucru foarte important pentru animatie - ele dau posibilitatea tratarii in

paralel de Java a mai multor activitati .

Un fir de executie este o parte a unui program care este configurata sa ruleze in timp ce restul programului executa altceva .

Prin separarea animatiei pe un fir de executie restul aplicatiei poate rula altceva .

Odata cu utilizarea firelor de executie trebuie sa facem unele modificari in fisierul nostru clasa :

- adaugam la declarare "implements Runnable"

- se creaza un obiect Thread in care pastram firul

- suprascriem metoda start() a applet-ului pentru a crea si lansa firul de executie

- suprascriem metoda stop() pentru a seta firul care se executa la null

- cream metoda run() care contine instructiunile ce fac appletul sa ruleze continuu animatia

Runnable este o interfata ; ea reprezinta sistemul prin care o clasa poate mosteni metode pe care altfel nu le-ar fi mostenit

de la superclasele sale . Aceste metode pot fi astfel disponibile oricarei metode care are nevoie de ele . Runnable contine o

metoda run() de care avem nevoie pentru a porni un fir de executie si de aceea trebuie implementata aceasta interfata in

cazul nostru .

Thread este o clasa din pachetul java.lang - asa incat nu avem nevoie de o instructiune import pentru a o utiliza . De obicei

obiectul de tip Thread se creaza in metoda start() si va avea o valoare null pana la crearea efectiva a obiectului - creare care

se face tot in metoda start() . Pentru a rula un fir de executie creat avem nevoie de metoda sa start() :

obiect_thread.start();

Apelarea acestei metode duce la apelarea metodei run() - mostenita prin interfata Runnable .

Metoda run() este cea mai importanta a appletului devenit fir de executie . Ea este folosita pentru a controla secventele

animatiei prin stabilirea tuturor operatiilor legate de desenare si de modificarile intre secventele de animatie .

Dupa definirea in metoda run() a comportamentului necesar firului de executie trebuie sa definim si metoda stop() - pentru

oprirea appletului .

- 85 -

Page 86: Programare Java

Acest lucru - oprirea - il putem face prin atribuirea valorii null obiectului Thread ; de fapt acest lucru nu duce la oprirea

automata a executie firului dar problema se rezolva prin metoda run() care va fi creata astfel incat sa permita rularea doar

daca obiectul Thread nu este null .

Pentru a clarifica problematica firelor de executie vom prezenta un applet care creaza un ceas - o animatie simpla - cu

actualizari constante .

In cadrul appletului vom folosi un ciclu while care ar putea fi periculos in conditii normale : acest ciclu ar monopoliza

resursele si practic nu am vedea nimic pe ecran deoarece Java ar astepta la infinit oprirea ciclului .

Appletul va defini un anumit font pentru afisare si un obiect de tip Date care pastreaza data curenta . Metodele start() si

stop() au rolul de a porni si respectiv opri firul de executie .

Metoda run() este cea mai importanta - cea care realizeaza de fapt toata animatia . Aici vom avea si buclucasul ciclu while

de mai sus ; primul lucru facut in ciclu este apelarea repaint() pentru redesenarea ferestrei . Tot aici vom intalni si o noua

metoda : sleep() . Aceasta metoda a clasei Thread determina o pauza in executie . Daca nu s-ar folosi aceasta metoda

appletul ar rula la viteza maxima , lucru care poate sa nu fie conform cu dorinta programatorului . Instructiunile try si catch

vor apare aici pentru tratarea erorilor si pentru moment le putem ignora .

Metoda paint() a appletului creaza o noua instanta a clasei Date - pentru folosirea acestei clase trebuie sa o importam , ea

fiind inclusa in java.util . De asemenea apare si metoda toString() a clasei Date , necesara pentru afisarea ca sir a datei si

orei . La fiecare apelare a metodei paint() vom avea astfel un nou obiect Date care va tine ora si data curente .

Sa vedem in continuare codul sursa al appletului descris anterior :

import java.awt.*;

import java.util.*;

public class CeasDigital extends java.applet.Applet implements Runnable {

Font fontul=new Font ("TimesRoman",Font.BOLD,24);

Date data;

Thread executabil;

public void start() {

if (executabil==null) {

executabil=new Thread(this);

executabil.start();

}

}

public void stop() {

if (executabil!=null) {

executabil=null;

}

}

public void run() {

Thread firExecutie=Thread.currentThread();

while (executabil==firExecutie) {

repaint();

try{

Thread.sleep(1000);

} catch (InterruptedException e) {}

}

}

public void paint(Graphics ecran) {

data=new Date();

ecran.setFont(fontul);

ecran.drawString(""+data.toString(),10,50);

}

}

EFECTUL DE FLICKERING AL ANIMATIE

Acest efect - cu denumirea in limba engleza , traducerea aproximativa fiind palpaire - este cauzat de modul de

reimprospatare a fiecarui cadru de animatie . Dupa cum am mai spus : apelul metodei repaint() duce automat la un apel al

metodei paint(). De fapt mai exista inca o metoda intermediara pe care Java o foloseste pentru a redesena ecranul aplicatiei;

- 86 -

Page 87: Programare Java

metoda update() - care sterge ecranul prin umplerea cu culoarea de fundal a ferestrei appletului si abia apoi se apeleaza

paint() .

Din cauza umplerii ecranului efectuata de metoda update() apare si acest efect de flickering .

In practica exista doua moduri de a evita acest eveniment suparator :

- suprascrierea metodei update() astfel incat aceasta sa nu mai stearga ecranul sau sa nu stearga partile de fereastra

care nu se vor modifica .

- suprascrierea metodelor paint() si update() impreuna cu folosirea dublei memorari ( double buffering ).

Vom prezenta mai intai prima metoda , suprascrierea lui update() - aceasta fiind cea mai simpla ; in multe cazuri insa ea nu

este aplicabila la programe mai complexe si va trebui utilizata cea de a doua tehnica de mai sus .

SUPRASCRIEREA METODEI UPDATE()

Implicit aceasta metoda are urmatorul cod sursa :

public void update(Graphics g) {

g.setColor(getBackground());

g.fillRect(0,0,size().width,size().height);

g.setColor(getForeground());

paint(g);

}

Putem alege o versiune de rezolvare a problemei palpairii prin anularea totala a stergerii ecranului . Aceasta solutie nu

poate fi aplicata pe scara larga dar in cazurile in care se poate aplica este cea mai simpla solutie .

Sa luam ca exemplu codul sursa de mai jos :

import java.awt.*;

public class AlternareCulori extends java.applet.Applet implements Runnable {

Font f=new Font("TimesRoman",Font.BOLD,50);

Color culori[]=new Color[50];

Thread executabil;

public void start() {

if (executabil==null) {

executabil=new Thread(this);

executabil.start();

}

}

public void stop() {

executabil=null;

}

public void run() {

float c=0;

for (int i=0;i<culori.length;i++) {

culori[i]=Color.getHSBColor(c,(float)1.0,(float)1.0);

c+=.02;

}

int i=0;

Thread firExecutie=Thread.currentThread();

while (executabil==firExecutie) {

setForeground(culori[i]);

repaint();

i++;

try {

Thread.sleep(200);

} catch (InterruptedException e) {}

if (i==culori.length) i=0;

}

}

public void paint(Graphics ecran) {

ecran.setFont(f);

- 87 -

Page 88: Programare Java

ecran.drawString("Priviti textul !",20,50);

}

}

Pentru a intelege cat mai bine appletul sa incercam un comentariu aproape linie cu linie al codului sursa :

Linia 5 defineste o variabila "culori" care desemneaza un tablou cu 50 de elemente . La pornirea appletului metoda run()

umple acest tablou cu obiecte Color . Crearea tabloului de culori poate fi realizata si in metoda paint() dar nu ar avea logica

, el creandu-se astfel la fiecare apelare a metodei paint() . In realitate este de ajuns crearea sa o singura data , astfel incat e

mai bine sa cream tabloul de culori in metoda init() .

Pentru a crea obiecte de culori diferite s-a folosit metoda getHSBColor() ; aceasta este parte a clasei Color si creaza un

obiect Color pe baza combinatiei intre nuanta ( hue ) , saturatie ( saturation ) si luminozitate ( brightness ) . Prin

incrementarea valorii nuantei putem astfel crea un obiect cu o culoare noua - avantajul crearii in acest fel a obiectelor Color

fiind rapiditatea mai mare a limbajului la implementarea acestei metode .

Pentru a se obtine animatia - adica modificarea continua a culorii textului afisat de applet - se utilizeaza un ciclu care

strabate tabloul de culori stabilind pe rand fiecare culoare din tablou drept culoare de desenare si apoi reapeleaza metoda

repaint() . Datorita conditiei din ciclul while procesul descris mai sus se va relua la infinit pana la oprirea fortata a

appletului .

La rularea appletului - e adevarat ca si in functie de hardware-ul disponibil - apare efectul de flicker ; acesta se datoreaza

aici faptului ca la fiecare desenare a sirului cu o noua culoare exista si o operatie de stergere totala a ecranului .

Acum vom opera modificarea metodei update() pentru a reduce acest efect suparator . Vom inlatura din metoda partea

responsabila cu stergerea ecranului , obtinand o metoda update() cu urmatorul cod sursa :

public void update(Graphics ecran) {

paint(ecran);

}

Cea de a doua metoda de evitare a flickerului este dubla memorare . Aceasta consta in procesul de a desena un cadru intreg

de animatie intr-o zona invizibila inainte de a-l copia in zona vizibila de pe ecran . Zona invizibila in care lucram se

numeste buffer ( sau memorie tampon ) .

Prin aceasta tehnica se creaza practic inca o suprafata de desenare , se fac toate operatiunile de desenare pe ea dupa care se

deseneaza dintr-o data intreaga suprafata in fereastra principala a appletului - toate acestea in loc sa se deseneze direct in

fereastra appletului , pe rand fiecare element .

Tehnica dublei memorari este destul de performanta , ea reusind sa elimine practic flickerul dar aduce dezavantajul unei

folosiri intensive a memoriei sistemului de calcul . Pentru a crea un applet bazat pe aceasta tehnica trebuie sa avem o

imagine pe care o desenam in buffer si un context grafic pentru acea imagine . Acestea vor simula efectul desenarii pe

suprafata appletului : contextul grafic ( de fapt o instanta a clasei Graphics ) care ofera metodele de desen si obiectul Image

, care memoreaza ceea ce se va desena .

Ca sa reusim implementarea corect a tehnicii de mai sus trebuie sa parcurgem patru etape .

Mai intai imaginea invizibila si contextul grafic trebuie stocate in variabile de instanta care vor putea apoi fi trimise

metodei paint() . Acest lucru se face sintactic la modul urmator:

Image imagineInvizibila;

Graphics invizibil;

In al doilea rand pe parcursul initializarii appletului vom crea obiecte Image si Graphics pe care le vom atribui acestor

variabile . Metoda createImage() returneaza o instanta a clasei Image , pe care apoi o putem transmite metodei

getGraphics() pentru a obtine un nou context pentru imaginea respectiva :

imagineInvizibila = createImage(size().width , size().height);

invizibil=imagineInvizibila.getGraphics();

In acest moment , ori de cate ori va trebui sa desenam pe ecran - cu metoda paint() - vom desena in contextul grafic

invizibil ; ca exemplu , pentru a desena o imagine numita img la pozitia 100,100 folosim linia de cod :

invizibil.drawImage(img,100,100,this);

In ceea ce priveste cuvantul cheie this folosit aici nu va faceti probleme pentru ceea ce reprezinta - va fi prezentat mai

detaliat in paginile urmatoare .

Ultima etapa , dupa ce s-a terminat de desenat totul in contextul invizibil , instructiunea urmatoare copiaza zona tampon

invizibila pe ecran :

- 88 -

Page 89: Programare Java

ecran.drawImage(imagineInvizibila,0,0,this);

Pentru a elimina si umplerea ecranului cu culoarea de fond ( operatia default a metodei update() ) este indicat sa

suprascriem si metoda update() la modul urmator :

public void update(Graphics g) {

paint(g);

}

Pentru a realiza in practica implementarea dublei memorari vom prezenta un exemplu de applet care deseneaza si misca un

cerc intre doua patrate colorate diferit - appletul se numeste "Dame" , dupa asemanarea rezultatului vizual cu o piesa din

acest joc :

import java.awt.*;

public class Dame extends java.applet.Applet implements Runnable {

Thread executabil;

int pozX=5;

int deplasareX=4;

Image imgInvizibila;

Graphics invizibil;

public void init() {

imgInvizibila=createImage(size().width,size().height);

invizibil=imgInvizibila.getGraphics();

}

public void start() {

if (executabil==null) {

executabil=new Thread(this);

executabil.start();

}

}

public void stop() {

executabil=null;

}

public void run() {

Thread firExecutie=Thread.currentThread();

while (executabil==firExecutie) {

pozX+=deplasareX;

if ((pozX>105)|(pozX<5)) {

deplasareX*=-1; }

repaint();

try {

Thread.sleep(100);

} catch (InterruptedException e) { }

}

}

public void update(Graphics ecran) {

paint(ecran);

}

public void paint(Graphics ecran) {

invizibil.setColor(Color.black);

invizibil.fillRect(0,0,100,100);

invizibil.setColor(Color.white);

invizibil.fillRect(100,0,100,100);

invizibil.setColor(Color.red);

invizibil.fillOval(pozX,5,90,90);

- 89 -

Page 90: Programare Java

ecran.drawImage(imgInvizibila,0,0,this);

}

public void destroy() {

invizibil.dispose();

}

}

Sa comentam putin programul de mai sus :

- variabila pozX este folosita pentru a muta cercul dintr-un loc in altul , ea pastrand coordonatele unde se afla piesa

la un moment dat . Valoarea variabilei se modifica continuu in metoda run() .

- primul pas pentru dubla memorare consta in crearea unui obiect Image care sa pastreze cadrul invizibil pana cand

acesta este complet si a unui obiect Graphics care sa permita desenarea in aceasta zona invizibila . Acest lucru il

fac liniile :

Image imgInvizibila;

Graphics invizibil;

- celor doua variabile amintite in randurile precedente li se atribuie obiecte create in metoda init() a appletului :

public void init() {

imgInvizibila=createImage(size().width,size().height);

invizibil=imgInvizibila.getGraphics();

}

- metoda paint() este modificata pentru a scrie zona tampon invizibila in locul obiectului principal Graphics ; practic

, doar ultima linie a metodei paint() afiseaza in fereastra appletului . Aceasta instructiune afiseaza cadrul de

animatie complet la coordonatele 0,0 . Deoarece obiectul imgInvizibil a fost creat de aceeasi dimensiune ca zona

de ecran el va acoperi complet fereastra appletului .

DISTRUGEREA CONTEXTELOR GRAPHICS

Ati remarcat in finalul exemplului de mai sus o metoda pe care nu am detaliat-o :

public void destroy() {

invizibil.dispose();

}

Pe scurt , aceasta metoda distruge obiectul invizibil .

Sa detaliem totusi putin problema !

Chiar daca recuperatorul de memorie Java functioneaza automat si distruge obiectele atunci cand nu mai este nevoie de ele

in program acest lucru nu este valabil si pentru obiectele Java care sunt create pentru a gestiona memoriile tampon din afara

ecranului .Obiectele ramase orfane si nefolosite ocupa astfel memorie si inrautatesc performantele Java ; pentru a rezolva

acest neajuns ar trebui sa folosim explicit metoda dispose() a clasei Graphics pentru a distruge aceste obiecte atunci cand

am terminat treaba cu ele .

Locul cel mai potrivit pentru a face acest lucru este metoda destroy() a appletului - metoda introdusa sporadic pe parcursul

unui curs anterior .

Metoda destroy() este apelata fara argumente , dupa modelul sintactic de mai jos :

public void destroy() {

graficaTampon.dispose();

}

INCARCAREA SI FOLOSIREA IMAGINILOR

Lucrul cu imagini in Java se realizeaza in principal prin intermediul clasei Image , inclusa in pachetul java.awt . Cand

lucram cu un applet vom folosi pentru incarcare si afisare a imaginilor metode ale claselor Applet si Graphics .

Pentru a afisa o imagine in appletul nostru trebuie intai sa o incarca in program din World Wide Web . Imaginile se vor

pastra in fisiere grafice separate de fisierele sursa si compilate Java , asa ca trebuie specificat clar locul in care le putem

gasi . Cand folosim clasa Image fisierele grafice pe care le utilizam trebuie sa fie de tip .GIF sau .JPG .

- 90 -

Page 91: Programare Java

O adresa web este reprezentata printr-un obiect URL . Clasa URL face parte din pachetul java.net care va trebui deci

importat pentru a-l pune la dispozitia programului nostru .

Obiectul URL este creat prin transmiterea adresei paginii web ca argument pentru metoda constructor a clasei URL , ca in

exemplul de mai jos :

URL u=new URL (http://www.site.com/imagini/imagine1.gif);

Dupa ce am creat obiectul URL il putem folosi pentru a crea un obiect Image care reprezinta propriu-zis fisierul grafic .

Pentru a incarca o imagine noua intr-un obiect Image clasa Applet contine o metoda numita getImage() , care poate fi

folosita in doua moduri :

- cu un singur argument - obiect URL , localizandu-se imaginea de la adresa exacta

- cu doua argumente : adresa URL de baza ca obiect URL si un sir care reprezinta calea relativa sau denumirea

fisierului care contine imaginea .

Ultima metoda este putin mai complicata dar ofera o mai mare flexibilitate .

Clasa Applet poseda doua metode care pot fi folosite pentru a crea o adresa URL de baza fara a folosi in program o adresa

fixa explicita ( lucru care ar face ca la orice modificare a adresei necesitate de applet sa fie necesara si o recompilare a

appletului ) :

- metoda getDocumentbase() returneaza obiectul URL care reprezinta directorul ce contine pagina web care

prezinta appletul

- metoda getCodeBase() care returneaza obiectul URL care reprezinta directorul unde se afla fisierul cu clasa

principala a appletului .

Calea relativa catre o resursa se foloseste ca al doilea argument pentru metoda getImage() si se modifica in functie de ce s-a

folosit in primul argument .

Sa luam un exemplu cu o pagina web cu adresa : http://www.site.com/index.html , care incarca o imagine din acelasi

director , imagine numita imagine1.gif . Pentru a folosi aceasta imagine in appletul nostru ne trebuie o instructiune de genul

:

Image imagine=getImage(getDocumentBase(),"imagine1.gif");

Practic , folosirea metodelor getDocumentBase() si getCodeBase() depinde de locul in care avem fisierele grafice : in

subdirectoarele appletului Java sau in subdirectoarele paginii web care apeleaza appletul . Datorita folosirii acestor metode

putem reloca pagina web cu tot cu applet fara a aparea probleme legate de eventuala necesitate de a recompila clasele Java .

DESENAREA IMAGINILOR

Dupa ce am pus o imagine intr-un obiect Image aceasta poat fi afisata in applet cu metoda drawImage() a clasei Graphics .

Pentru a afisa o imagine la dimensiunile reale vom apela metoda cu patru argumente :

- obiectul Image pentru afisare

- coordonatele x si y ale coltului din stanga sus ale locului unde vrem sa afisam imaginea

- cuvantul cheie this

Daca fisierul grafic trebuie afisat la o alta scara decat originalul trebuie sa folosim sase argumente pentru metoda

drawImage() :

- obiectul Image de afisat

- coordonatele x si y ale imaginii

- latime imaginii in pixeli

- inaltimea imaginii in pixeli

- cuvantul cheie this

Scalarea imaginii are efect doar pentru afisarea in applet , obiectul propriu-zis nefiind alterat de aceste apeluri de metoda .

Pentru a afla dimensiunile unei imagini afisate avem la dipsozitie metodele getHeight() si getWidth() care returneaza

inaltimea si respectiv latimea imaginii afisate .

Ultimul argument al metodei drawImage este cuvantul cheie this - element folosit in general intr-un obiect pentru a face o

referinta la el insusi .

Folosirea sa in acest context este necesara pentru a identifica un applet care poate urmari incarcarea imaginii de pe web .

Incarcarea imaginii este urmarita prin intermediul unei interfete ImageObserver . Clasele care implementeaza aceasta

- 91 -

Page 92: Programare Java

interfata - printre care si Applet - pot observa gradul de incarcare al unei imagini . Acest lucru poate fi folositor de exemplu

pentru un program care sa afiseze altceva in timpul incarcarii unor imagini ( procese care uneori pot dura destul de mult ) .

In continuare vom prezenta un exemplu de afisare a unor imagini la scara originala si cu dimensiuni marite :

import java.awt.*;

public class Imagine extends java.applet.Applet {

Image poza;

public void init() {

poza=getImage(getCodeBase(),"poza1.gif");

}

public void paint(Graphics ecran) {

int latime=poza.getWidth(this);

int inaltime=poza.getHeight(this);

int xPoz=10;

setBackground(Color.pink);

ecran.drawImage(poza,10,10,latime,inaltime,this);

xPoz+=latime+5;

ecran.drawImage(poza,xPoz,10,latime*4,inaltime*4,this);

}

}

Appletul de mai sus presupune ca dispunem de un fisier grafic numit poza1.gif , pe care dorim sa-l afisam mai intai la

dimensiunile sale reale si apoi cu latime si inaltimea de patru ori mai mari .

Variabila xPoz contine valoarea coordonatei x a locului unde se doreste inceperea afisarii imaginii .

FOLOSIREA SUNETULUI

Clasa Applet are posibilitatea de a reda si sunet . De la versiunea 2 a limbajului Java putem folosi fisiere audio in mai multe

formate : AIFF , AU , MIDI si WAV .

Cea mai simpla metoda de incarcare si redare a unui sunet este prin utilizarea metodei play() a clasei Applet . Aceasta

metoda are doua forme de apelare :

- cu un argument - obiect URL , va incarca si reda fisierul audio de la adresa servita ca argument

- cu doua argumente - a adresa URL de baza si o cale directoare . Primul argument este de cele mai multe ori un

apel al metodei getDocumentBase() sau getCodeBase() .

Instructiunea de mai jos incarca si reda un fisier audio numit sunet.wav , aflat in acelasi director cu appletul :

play(getCodeBase(),"sunet.wav");

Metoda play() incarca si reda sunetul cat mai repede posibil . In cazul in care fisierul de sunet nu este disponibil la adresa

servita metodei play() nu vom obtine nici un mesaj de eroare - pur si simplu nu se va auzi nici un sunet !

Avem posibilitatea de a reda continuu un sunet , de a-l porni si a-l opri la dorinta . Acesta lucru se poate face incarcand

fisierul audio intr-un obiect AudioClip , folosind metoda getAudioClip a acestuia . Clasa AudioClip este inclusa in pachetul

java.awt .

Metoda getAudioClip() primeste unul sau doua argumente . Primul argument ( care poate fi si unic ) este un obiect URL

care identifica fisierul de sunet iar al doilea poate fi o referinta la cale .

In exemplul de mai jos putem vedea cum se incarca un fisier audio - "sunet.wav" , aflat intr subdirectorul "audio" al

appletului - intr-un obiect AudioClip :

AudioClip clip=getAudioClip(getCodeBase(),"audio/sunet.wav");

Metoda getAudioClip() poate fi apelata numai in cadrul unui applet . Pentru incarcarea unui fisier audio intr-o aplicatie

independenta Java trebuie sa folosim metoda newAudioClip() a clasei Applet :

AudioClip clip=newAudioClip("audio/sunet.wav");

- 92 -

Page 93: Programare Java

Odata creat obiectul AudioClip putem apela si metodele play() , stop() sau loop() ale acestuia . Play() reda sunetul , stop()

opreste redarea sunetului iar loop() provoaca redarea continuu a fisierului audio .

Spre deosebire de apelarea simpla play() pentru un anumit fisier de sunet ( caz in care inexistenta fisierului audio nu

provoaca nici o eroare ) folosirea metodelor getAudioClip() sau newAudioClip() poate duce la erori in cazul in care fisierul

de sunet indicat de argumente nu exista ; acest lucru se datoreaza faptului ca obiectul AudioClip creat de noi va avea

valoarea null , iar redarea unui obiect null produce o eroare .

In cazul in care vrem sa redam mai multe sunete simultan nu exista nici o problema - vom folosi mai multe fire de executie

.

Trebuie mentionata si o problema - in cazul in care utilizam o redare continuua a unui sunet in appletul nostru oprirea

firului de executie al appletului nu va duce si la oprirea automata a sunetului . In practica daca un utilizator va trece in alta

pagina web sunetul va continua sa se auda ! Rezolvarea acestei probleme se face prin utilizarea metodei stop() pentru

sunetul redat in acelasi timp cu oprirea firului de executie al appletului .

In continuare avem un exemplu care reda continuu un sunet - sunet1.wav - si o data la fiecare 5 secunde reda si fisierul

sunet2.wav :

import java.awt.*;

import java.applet.*;

public class CicluAudio extends java.applet.Applet implements Runnable {

AudioClip sunetFundal;

AudioClip bip;

Thread executabil;

public void start() {

if (executabil==null) {

executabil=new Thread(this);

executabil.start();

}

}

public void stop() {

if (executabil!=null) {

if (sunetFundal!=null)

sunetFundal.stop();

executabil=null;

}

}

public void init() {

sunetFundal=getAudioClip(getCodeBase(),"sunet1.wav");

bip=getAudioClip(getCodeBase(),"sunet2.wav");

}

public void run() {

if (sunetFundal!=null) sunetFundal.loop();

Thread firExecutie=Thread.currentThread();

while (executabil==firExecutie) {

try {

Thread.sleep(5000);

} catch (InterruptedException e) {}

if (bip!=null) bip.play();

}

}

public void paint(Graphics ecran) {

ecran.drawString("Se aude sunet !",50,50);

}

}

- 93 -

Page 94: Programare Java

Programare Java

Curs – 9

CREAREA DE INTERFETE GRAFICE PENTRU APPLETURI

Realizarea unei astfel de interfete in limbajul Java se bazeaza in principal pe

biblioteca AWT ( Abstract Windowing Toolkit ) , care contine un set de clase pentru

crearea si folosirea unor astfel de interfete grafice pentru utilizator .

AWT

Dupa cum am mai spus AWT reprezinta un set de clase care ne ajuta - printre altele -

sa cream o interfata grafica utilizator care sa reactioneze la datele de intrare primite de

la mouse sau tastatura .

Deoarece Java este un limbaj independent de platforma AWT ofera modalitatea de a

proiecta o interfata care sa fie la fel reprezentata si cu aceleasi caracteristici pe orice

sistem pe care ar rula . Folosind pachetul AWT avem de luat in calcul mai multe

elemente care compun o interfata grafica :

- componente - orice element poate fi practic plasat pe o interfata utilizator :

butoane , liste derulante , meniuri popup , casete de validare sau campuri de

text .

- containere - acestea reprezinta de fapt componente care pot contine la randul

lor alte componente . Un exemplu de container este chiar fereastra Applet , iar

alte exemple ar putea fi panouri , casete de dialog sau ferestre independente .

- administratori de dispunere - acestia sunt de fapt niste obiecte care definesc

modul de dispunere a componentelor intr-un container . Un astfel de

administrator nu este un element propriu-zis vizual , nu vedem pe ecran un

astfel de obiect , efectele sale sunt insa vizibile .

Toate clasele AWT sunt bineinteles incluse in pachetul java.awt . Pentru a le putea

folosi trebuie importat acest pachet explicit la inceputul codului nostru sursa .

Importarea intregului pachet are ca rezultat disponibilizarea pentru programator a

tuturor componentelor , containerelor si administratorilor de dispunere folositi pentru

realizarea unei interfete grafice . O alta modalitate de a putea folosi clasele necesare

este si importarea individuala a claselor necesare .

COMPONENTELE INTERFETEI GRAFICE

Acestea sunt pozitionate in cadrul interfetei pe care o construim prin adaugarea lor

intr-un container . Acesta este chiar el o componenta si deci poate fi la randul sau

adaugat in alt container . Cel mai usor mod de a demonstra cum se proiecteaza o

interfata este folosirea containerului cu care am lucrat in ultimele cursuri - clasa

Applet .

- 94 -

Page 95: Programare Java

ADAUGAREA DE COMPONENTE LA UN CONTAINER

Exista doar doi pasi care trebuie urmati pentru a adauga o componenta la un container

:

- crearea componentei respective

- apelarea metodei add() a containerului pentru componenta respectiva

Datorita faptului ca un Applet este un container putem folosi metoda add() in cadrul

unui applet pentru a adauga o componenta direct in fereastra Applet .

Fiecare componenta AWT la randul ei este o clasa , deci componenta este creata

propriu-zis prin crearea unui obiect al clasei respective .

De exemplu , clasa Button reprezinta butoanele din cadrul unei interfete grafice . Un

buton se creaza specificand eticheta sa in metoda constructorului , ca mai jos :

Button butonNou=new Button("Apasa aici");

Parametru de tip string primit de constructor se refera la textul care se va afisa pe

suprafata butonului .

Dupa ce s-a creat componenta cea mai simpla metoda de a o adauga este folosirea

metodei add() cu numele componentei ca argument :

add(butonNou);

Adaugarea componentei nu duce automat si la desenarea ei pe ecran . Ea va fi afisata

doar dupa apelul metodei paint() a containerului ; putem folosi si metoda repaint()

pentru a forta afisarea unor noi componente eventual adaugate .

La momentul adaugarii unei componente intr-un container se observa ca nu i se

acorda acesteia nici o pozitionare - prin coordonate x si y ; acesta pozitionare se face

doar prin administratorii de dispunere . In cazul in care nu specificam un

administrator de dispunere se foloseste automat un administrator Java numit

FlowLayout - acesta ordoneaza componentele de la stanga la dreapta , iar cand nu mai

este loc pe linie se trece la urmatoarea linie , mai jos .

Pentru crearea componentelor in applet vom folosi metoda init() . In continuare aveti

un exemplu de creare a unui buton in cadrul unui applet ; acest buton are un text afisat

pe el si va fi afisat propriu-zis doar dupa apelarea metodei paint() :

import java.awt.*;

public class Buton extends java.applet.Applet {

String mesaj="Numele butonului . Nu apasati";

Button butonNou=new Button(mesaj);

public void init() {

add(butonNou);

}

}

- 95 -

Page 96: Programare Java

ETICHETE

O eticheta este de fapt cea mai simplista componenta a unei intergete grafice , ea fiind

implementata prin clasa Label . Etichetele se folosesc pentru a identifica rolul

celorlalte componente si nu pot fi modificate direct de utilizator - de fapt reprezinta

niste siruri afisate in dreptul celorlalte componente pentru a ne arata cu ce se ocupa

componenta respectiva .

Folosirea etichetelor pentru text se foloseste in locul metodei drawString() din mai

multe cauze :

- o eticheta este desenata automat si nu are nevoie de tratare explicita de catre

metoda paint()

- etichetele pot fi dispuse in fereastra conform cu administratorii de dispunere

folositi si nu nevoie de o pozitionare prin coordonate date in pixeli

Pentru a crea o eticheta putem incerca mai multemetode :

- Label() - aceasta instructiune creaza o eticheta goala , cu textul aliniat automat

la stanga

- Label(sir) - creaza o eticheta cu textul specificat prin variabila de tip String ,

alinierea textului fiind la stanga

- Label(sir,argument2) - creaza o eticheta cu sirul dat ca text si cu alinierea

indicata de argumentul al doilea . Pentru a seta alinierea se pot folosi

variabilele de clasa : Label.RIGHT , Label.LEFT si Label.CENTER , care duc

la alinierea textului la dreapta , la stanga si respectiv centrat .

Pentru a modifica textul etichetei dupa crearea acesteia putem folosi metoda

setText(sir) ; noul sir dat ca parametru este afisat dupa reimprospatarea componentei .

O alta metoda folositoare este si getText() care ne returneaza valoarea textului

etichetei .

In continuare avem un exemplu de applet in care s-au creat trei etichete ; in codul

sursa apare si un obiect de tip GridLayout - acesta este folosit pentru a putea vedea

efectul alinierii etichetelor . In cazul in care nu l-am fi folosit Java ar fi apelat implicit

administratorul FlowLayout care nu ne-ar mai fi permis sa aliniem etichetele .

Administratorii de dispunere vor fi prezentati mai tarziu detaliat .

import java.awt.*;

public class Etichete extends java.applet.Applet {

Label stanga=new Label("Aliniat la stanga");

Label dreapta=new Label("Aliniat la dreapta",Label.RIGHT);

Label centrat=new Label("Aliniat pe centru",Label.CENTER);

Font f=new Font("Helvetica",Font.BOLD,18);

GridLayout dispunere=new GridLayout(3,1);

public void init() {

setFont(f);

setLayout(dispunere);

add(stanga);

- 96 -

Page 97: Programare Java

setForeground(Color.green);

add(centrat);

setForeground(Color.blue);

add(dreapta);

}

}

BUTOANE

Un buton reprezinta de fapt o zona pe care putem efectua un clic ; el poate fi creat cu

ajutorul clasei Button . In general aceste butoane sunt folosite pentru a declansa o

actiune atunci cand se efectueaza un clic pe suprafata lor .

Ca sa cream un buton trebuie sa urmam una dintre caile urmatoare : fie apelam

constructorul Button() care ne creaza un buton fara nici un text fie apelam

constructorul cu un argument de tip String care este de fapt chiar textul butonului .

Odata creat acest buton ii mai putem modifica textul cu ajutorul metodei setLabel()

sau putem folosi metoda getLabel() pentru a afla textul acestui buton .

OBS. : setLabel() si getLabel() nu au legatura cu clasa Label , ele se refera doar la

clasa Button .

In continuare avem un exemplu de applet care va prezenta cinci butoane pentru

functiile unui casetofon ( de exemplu ) :

import java.awt.*;

public class Casetofon extends java.applet.Applet {

Button inapoi=new Button("Inapoi");

Button inainte=new Button("Inainte");

Button play=new Button("Play");

Button stop=new Button("Stop");

Button pauza=new Button("Pauza");

public void init() {

add(inapoi);

add(inainte);

add(pauza);

add(stop);

add(play);

}

}

CASETE DE VALIDARE

- 97 -

Page 98: Programare Java

Aceste componente , numite in engleza checkbox , sunt in practica niste casete patrate

care pot fi bifate sau nu cu ajutorul unui clic de mouse . Scopul lor este in general de a

selecta sau deselecta anumite facilitati ale unui program .

In majoritatea cazurilor in care se folosesc casete de validare acestea sunt neexclusive

, adica oricare dintre casete poate avea valoare bifat sau nu , putand deci fi bifate la un

moment dat chiar si toate casetele sau nici una . O alta modalitate de folosire a acestor

casete este si gruparea lor care duce la realizarea asa numitelor butoane radio ;

proprietatea acestora de baza este faptul ca la un moment dat poate fi activ ( bifat )

doar un singur caz , o singura caseta .

Ambele tipuri de casete de validare sunt implementate cu ajutorul clasei Checkbox .

Pentru a crea o caseta de validare neexclusiva putem folosi unul dintre urmatorii

constructori :

- Checkbox() - care creaza o caseta de validare fara eticheta si nevalidata (

nebifata )

- Checkbox(sir) - care creaza o caseta de validare cu eticheta fiind sirul dat ca

parametru si nevalidata .

Odata creat un obiect Checkbox se foloseste metoda setState(boolean) pentru a

modifica starea acestuia : valoarea true pentru a bifa caseta si valoarea false pentru a

debifa caseta de validare . Metoda getState() returneaza o valoare Boolean care ne

indica starea de validare a casetei la momentul respectiv .

In listingul de mai jos avem un exemplu de applet care creaza cinci casete de validare

neexclusive care permit selectarea unor marci de automobile :

import java.awt.*;

public class Bifare extends java.applet.Applet {

Checkbox caseta1=new Checkbox("Volvo");

Checkbox caseta2=new Checkbox("BMW");

Checkbox caseta3=new Checkbox("Mercedes");

Checkbox caseta4=new Checkbox("Audi");

Checkbox caseta5=new Checkbox("Dacia");

public void init() {

add(caseta1);

add(caseta2);

add(caseta3);

add(caseta4);

add(caseta5);

caseta5.setState(true);

}

}

In cazul in care dorim sa grupam mai multe casete de validare intr-un grup pentru a

realiza niste butoane radio vom crea un obiect CheckboxGroup :

CheckboxGroup grup=new CheckboxGroup();

- 98 -

Page 99: Programare Java

Acest obiect va pastra starea tuturor casetelor din grupul respectiv si va fi folosit ca

argument suplimentar pentru constructorul Checkbox . Pentru a crea o caseta de

validare care apartine unui grup vom folosi o instructiune de genul :

Checkbox(sir,grupCaseteValidare,boolean)

Aceasta instructiune va crea o caseta cu eticheta conform a cu sirul si cu starea de

bifare sau nebifare setata de argumentul de tip boolean .

In continuare avem un exemplu care creaza un grup cu trei casete de validare :

import java.awt.*;

public class Bifare extends java.applet.Applet {

CheckboxGroup grup=new CheckboxGroup();

Checkbox caseta1=new Checkbox("Volvo",grup,false);

Checkbox caseta2=new Checkbox("BMW",grup,false);

Checkbox caseta3=new Checkbox("Mercedes",grup,true);

Checkbox caseta4=new Checkbox("Audi",grup,false);

Checkbox caseta5=new Checkbox("Dacia",grup,false);

public void init() {

add(caseta1);

add(caseta2);

add(caseta3);

add(caseta4);

add(caseta5);

}

}

In cazul in care vrem sa modificam starea de validare a unui buton radio dintr-un grup

putem folosi metoda setCurrent(validare) . Putem folosi si metoda getCurrent() pentru

a intoarce valoarea curenta de bifare a unei casete de validare .

LISTE DE OPTIUNI

Acestea sunt create cu ajutorul clasei Choice si permit alegerea unei singure optiuni

dintr-o lista derulanta pe verticala .

Pentru a crea o astfel de lista trebuie mai intai sa cream un obiect Choice care va

pastra lista propriu-zisa :

Choice lista=new Choice();

Elementele listei se adauga la aceasta prin metoda addItem(sir) a obiectului de tip

Choice . Metoda addItem() poate fi folosita si dupa ce lista noastra a fost deja

adaugata la un container .

In codul sursa de mai jos s-a realizat un applet care permite selectarea unei echipe de

fotbal dintr-o lista de patru echipe :

import java.awt.*;

- 99 -

Page 100: Programare Java

public class ListaSelectie extends java.applet.Applet {

Choice lista=new Choice();

Label eticheta=new Label("Echipa care credeti ca va castiga Liga Campionilor in

2002 :");

public void init() {

add(eticheta);

lista.addItem("Real Madrid");

lista.addItem("Manchester United");

lista.addItem("Bayer Leverkusen");

lista.addItem("Barcelona");

add(lista);

}

}

In cadrul clasei Choice exista mai multe metode folositoare pentru controlul asupra

unei liste de selectie :

- getItem(int) - aceasta metoda returneaza textul optiunii din pozitia specificata

de argumentul intreg , prima optiune avand pozitia 0

- countItems() - intoarce numarul de elemente ale listei

- getSelectedIndex() - intoarce pozitia elementului care este selectat la acel

moment

- getSelectedItem() - intoarce textul elementului selectat la acel moment

- select(int) - selecteaza elementul aflat pe pozitia specificata de argument

- select(String) - selecteaza primul element din lista care are sirul dat ca

parametru drept text

OBS. : Trebuie sa facem cateva observatii legate de unele metode prezentate in

paragrafele de mai sus :

- metoda Checkbox(String,grup,boolean) a fost inlocuita in Java 2 cu metoda

Checkbox(String,boolean,grup); putem folosi in continuare si prima varianta

dar la compilare vom obtine un mesaj legat de deprecierea metodei respective

- metoda addItem(String) folosita pentru a adauga un element intr-o lista de

optiuni se va inlocui incepand cu Java 2 cu metoda add(String) a clasei Choice

CAMPURI DE TEXT

Textul introdus in applet prin componentele precedente nu era modificabil de catre

utilizator , doar programatorul avand posibilitatea de a face acest lucru . Campurile de

text dau posibilitatea utilizatorului sa poata introduce propriul text in program . Aceste

componente ale interfetei sunt implementate cu ajutorul clasei TextField .

Pentru a crea un camp de text putem folosi una dintre urmatoarele patru variante :

- TextField() - va crea un camp gol si fara o latime specificata

- TextField(int) - va crea un camp gol care are o latime pentru a afisa un numar

de caractere specificat de argumentul intreg .

- TextField(String) - creaza un camp de text completat cu sirul dat ca parametru

- 100 -

Page 101: Programare Java

- TextField(String,int) - creaza un camp completat cu sirul dat ca parametru si

cu latimea data de argumetul intreg . OBS. : incepand cu Java 2 se recomanda

folosirea acestui constructor in locul lui TextField(int) .

Atributele responsabile cu latimea campului de text au de fapt importanta doar in

cazul folosirii unor administratori de dispunere care nu redimensioneaza

componentele - ca de exemplu FlowLayout .

In cazul in care vrem ca textul introdus de la tastatura de utilizator sa nu fie vizibil in

clar - de exemplu in cazul parolelor - putem folosi o metoda numita

setEchoCharacter(char) care va primi ca argument un caracter ce trebuie inclus intre

apostroafe ( de exemplu : '@' ) .

OBS. : Incepand cu Java 2 metoda setEchoCharacter(char) se poate inlocui cu metoda

setEchoChar(char) .

In continuare este prezentat un applet care utilizeaza mai multe campuri de text in clar

si un camp de text care ascunde textul introdus de utilizator :

import java.awt.*;

public class CampuriText extends java.applet.Applet {

Label eticheta1=new Label("Nume : ");

TextField nume=new TextField(30);

Label eticheta2=new Label("Prenume : ");

TextField prenume=new TextField(30);

Label eticheta3=new Label("Parola : ");

TextField parola=new TextField(30);

public void init() {

add(eticheta1);

add(nume);

add(eticheta2);

add(prenume);

add(eticheta3);

parola.setEchoChar('@');

add(parola);

}

}

Clasa TextField are si ea cateva metode foarte des folosite pentru a controla campurile

de text :

- metoda getText() - returneaza textul continut de camp

- metoda setText(String) - completeaza campul de text cu sirul specificat ca

argument

- metoda setEditable(boolean) - determina daca respectivul camp de text poate

fi sau nu modificat de utilizator . Argumentul false duce la blocarea campului

- 101 -

Page 102: Programare Java

pentru introducerea de text iar argumentul true permite introducerea de text

din partea utilizatorului

- metoda isEditable() - returneaza starea unui camp de text printr-o valoare

booleana ; daca respectivul camp de text poate fi editat va returna true iar daca

nu este editabil va returna false

ZONE DE TEXT

Aceste componente - numite text area in engleza - sunt de fapt niste campuri de text

care contin mai multe linii ( spre deosebire de campurile de text clasice care apar doar

pe un rand ) . O zona de text poseda si bare de scroll pentru eventualul text care nu

incape in partea vizibila a zonei de text .

Pentru a crea o astfel de zona de text trebuie sa folosim unul dintre cei patru

constructori de mai jos :

- TextArea() - creaza o zona de text goala cu inaltime si latime nespecificate

- TextArea(int,int) - creaza o zona goala care contine numarul de linii dat de

primul argument si are latimea data de numarul de caractere care este

specificat de cel de-al doilea argument intreg

- TextArea(String) - creaza o zona de text care contine sirul dat ca argument

- TextArea(String,int,int) - creaza o zona de text care contine sirul dat ca

argument , numarul de linii dat de primul argument intreg si lungimea unei

linii de atatea caractere cat reprezinta al doilea argument intreg

In exemplul de mai jos avem o zona de text gata completata cu un text :

import java.awt.*;

public class ZonaText extends java.applet.Applet {

String sir="Text introdus pentru a arata modalitatea de a introduce \ntext

predefinit in cadrul unei zone de text create in limbajul Java .";

TextArea zona;

public void init() {

zona=new TextArea(sir,10,70);

add(zona);

}

}

In cazul zonelor de text mai trebuie sa mentionam ca ele sunt inrudite cu campurile de

text nu numai din punct de vedere logic ci si ca ierarhie de clase Java ; ambele

componente mostenesc de fapt o clasa numita TextComponent , clasa care de fapt

poseda metodele setText() , getText() , setEditable() si isEditable() si astfel aceste

metode sunt disponibile si clasei TextArea .

Zonele de text poseda si ele unele metode proprii foarte utile :

- 102 -

Page 103: Programare Java

- metoda insertText(String,int) - insereaza sirul dat ca parametru la pozitia data

de argumentul intreg ; prima valoare a indexului este 0 . OBS. : Incepand cu

Java 2 metoda se recomanda a se inlocui cu metoda insert(String,int) .

- metoda replaceText(String,int,int) - inlocuieste textul aflat intre pozitiile

indicate de argumentele intregi cu sirul dat ca prim argument . OBS. : Si

aceasta metoda are o alta versiune incepand cu Java 2 , si anume metoda

replace(String,int) .

LISTE DERULANTE

Aceste componente - scrolling lists - sunt create cu ajutorulclasei List si sunt

asemanatoare cu listele de optiuni avand de fapt doar doua diferente majore :

1. o lista derulanta poate fi configurata astfel incat sa poata fi selectate mai multe

optiuni

2. aceste liste se prezinta ca o zona de text in care sunt afisate mai multe optiuni

iar daca lista contine mai multe optiuni decat pot fi afisate atunci apare bara de

scroll .

Lista derulanta este definita prin crearea unui obiect List la care apoi se adauga

elementele propriu-zise ale listei . Pentru a realiza acest lucru putem folosi unul dintre

constructorii de mai jos :

- List() - creaza o lista vida care permite o selectie unica de element

- List(int , boolean) - creaza o lista derulanta care are un numar de elemente

vizibile la un moment dat specificat prin argumentul intreg iar argumentul

boolean indica daca pot fi selectate mai multe optiuni - in cazul posibilitatii

selectarii mai multor optiuni argumentul trebuie sa aiba valoarea true

Odata creat un obiect List ii folosim metoda addItem(String) pentru a adauga

elemente la acest obiect - OBS. : Ca si in cazul listei de optiuni , incepand cu Java 2

metoda aceasta se recomanda a fi inlocuita cu metoda add(String) a clasei List .

Ca si orice alta componenta si lista derulanta trebuie adaugata intr-un container cu

ajutorul metodei add() .

Exemplul de mai jos ne prezinta o lista derulanta cu patru elemente vizibile la un

moment dat ( dintr-un total de sase elemente ale listei ) :

import java.awt.*;

public class ListaDerulanta extends java.applet.Applet {

List lista=new List(4,true);

Label eticheta=new Label("Selectati ziarele pe care le cititi : ");

public void init() {

add(eticheta);

lista.add("Evenimentul zilei");

lista.add("Curentul");

lista.add("Libertatea");

lista.add("ProSport");

- 103 -

Page 104: Programare Java

lista.add("Gazeta Sporturilor");

lista.add("Monitorul oficial");

add(lista);

}

}

Ca si in cazul celorlalte componente si listele derulante au cateva metode des utilizate

in conjunctie cu ele :

- metodele getItem(int) , countItems() , getSelectedIndex() , getSelectedItem() si

select(int) sunt aceleasi ca si pentru listele de optiuni . Metoda countItems()

are un inlocuitor incepand cu Java 2 in persoana metodei getItemCount() - atat

in cazul listelor de optiuni cat si al listelor derulante .

- metoda getSelectedIndezes() - intoarce un tablou de intregi care contine

pozitiile fiecarui element selectat .

- metoda getSelectedItems() - intoarce un tablou de siruri care contine textul

fiecarui element selectat .

BARE DE SCROLL

Componentele numite bare de derulare - scrollbars - sunt cele care permit selectarea

unei valori prin deplasarea unei casete intre doua sageti . Dupa cum am vazut in cazul

componentelor anterioare mai multe dintre acestea au incorporate astfel de bare de

derulare ( de exemplu zonele de text sau listele derulante ) . Clasa Scrollbar este cea

responsabila pentru alte tipuri noi de bare de scroll . O astfel de bara de scroll poate fi

orizontala sau verticala .

Barele de derulare sunt folosite in general pentru a specifica valorile minime si

maxime care pot fi stabilite prin utilizarea componentei .

Pentru a crea o bara de scroll trebuie sa folosim unul dintre constructorii urmatori :

- Scrollbar() - creaza o bara de scroll verticala cu valorile minima si maxima

setate initial la 0

- Scrollbar(int) - creaza o bara de scroll cu valorile maxima si minima setate la 0

iar orientarea este data de argumentul intreg . Acest argument poate lua ca

valori urmatoarele variabile de clasa : Scrollbar.HORIZONTAL ,

Scrollbar.VERTICAL .

- Scrollbar(int,int,int,int,int) - se creaza astfel o bara de scroll cu caracteristicile

urmatoare :

- primul argument stabileste orientarea cu ajutorul variabilelor de clasa

prezentate mai sus

- valoarea initiala a barei de scroll , care trebuie sa fie intre valorile

minima si maxima ale barei

- latimea sau inaltimea generala a casetei folosite pentru modificarea

valorii barei de scroll ; in cazul in care se foloseste marimea predefinita

a acestei casete vom folosi valoarea 0 pentru acest al treilea argument

- valoarea minima a barei de scroll

- valoarea maxim a barei de scroll

- 104 -

Page 105: Programare Java

In exemplul de mai jos se creaza o bara de scroll orizontala . Pentru a afisa bara de

scroll pe toata latimea ecranului trebuie sa folosim un administrator de dispunere - si

se va folosi GridLayout pentru a imparti ecranul in 15 linii iar bara noastra de scroll

va acoperi prima linie astfel creata a ecranului ; caseta care gliseaza pe bara noastra de

scroll va fi initial la o cincime din lungimea barei si va avea ca latime tot o cincime

din lungimea barei , lucru setat din constructorul folosit pentru crearea barei noastre :

import java.awt.*;

public class BaraScroll extends java.applet.Applet {

GridLayout admin=new GridLayout(15,1);

Scrollbar bara=new Scrollbar(Scrollbar.HORIZONTAL,20,20,1,100);

public void init() {

setLayout(admin);

add(bara);

}

}

Si clasa Scrollbar ofera cateva metode practice cum ar fi :

- metoda getValue() - returneaza valoarea curenta a barei de derulare .

- metoda setValue(int) - seteaza valoarea curenta a barei

SUPRAFETE DE DESENARE

Aceste componente sunt in general folosite ca loc pentru afisarea de imagini sau

animatii . Bineinteles ca putem desena si pe alte componente - ca de exemplu in

fereastra Applet - insa obiectele Canvas ( aceasta fiind clasa responsabila de

implementarea suprafetelor de desenare ) sunt cele mai simplu de folosit in acest scop

.

Pentru a folosi o suprafata de desenare trebuie mai intai sa cream o subclasa a clasei

Canvas ; aceasta subclasa se poate ocupa de toate operatiunile de desenare care

trebuie sa aiba loc in metoda sa paint() .

Dupa ce s-a creat o subclasa Canvas aceasta poate fi folosita in aplicatia noastra prin

apelarea constructorului sau si prin adaugarea noului obiect Canvas intr-un container .

Pentru a exemplifica teoria de mai sus sa studiem putin applet urmator ; acesta

deseneaza o cruce in centrul ferestrei Applet si poate muta centru acesteia daca

fereastra care publica appletul este redimensionata :

import java.awt.*;

public class Cruce extends java.applet.Applet {

GridLayout admin=new GridLayout(1,1);

canvasNou suprafata=new canvasNou();

- 105 -

Page 106: Programare Java

public void init() {

setLayout(admin);

add(suprafata);

}

}

class canvasNou extends java.awt.Canvas {

public void paint(Graphics ecran) {

int x=getSize().width/2;

int y=getSize().height/2;

ecran.setColor(Color.blue);

ecran.drawLine(x-10,y,x-2,y);

ecran.drawLine(x+10,y,x+2,y);

ecran.drawLine(x,y-10,x,y-2);

ecran.drawLine(x,y+10,x,y+2);

}

}

Acest applet contine in codul sau sursa doua clase ; prima dintre ele :- Cruce , este

chiar appletul insusi . A doua clasa este o clasa creata de noi ca fiind o subclasa a

clasei Canvas .

Clasa Cruce creaza un obiect GridLayout care va fi stabilit drept administrator de

dispunere cu ajutorul metodei setLayout() , creaza un obiect de tipul celei de a doua

clase create in applet si apoi adauga acest obiect in containerul desemnat de insasi

fereastra Applet . Datorita folosirii administratorului de dispunere suprafata de

desenare numita "suprafata" va cuprinde de fapt toata suprafata ferestrei appletului .

In cadrul clasei canvasNou se determina mai intai mijlocul ferestrei Applet - lucru

facut dinamic astfel incat totdeauna , indiferent de eventuala redimensionare a

ferestrei , variabilele x si y vor contine coordonatele corecte pentru jumatatea laturilor

ferestrei . Tot aici este setata si culoare pentru desenare , culoarea albastra . Trebuie

atrasa atentia ca aceasta metoda - ca si metodele de desenare propriu-zisa a liniilor ce

compun vrucea - este apelata pentru obiectul de tip Graphics al metodei paint() si nu

pentru suprafata de desenare . Obiectul ecran , de tipul Graphics , se ocupa de toate

eventualele operatii de desenare care au loc pe obiectul suprafata de desenare . Finalul

clasei canvasNou se ocupa de desenarea directa a celor patru linii care formeaza

crucea , fiecare linie avand cate 6 pixeli lungime si terminandu-se la 4 pixeli de

punctul care reprezinta exact centrul ferestrei.

- 106 -

Page 107: Programare Java

Programare Java

Curs – 10

MANAGEMENTUL UNEI INTERFETE GRAFICE

Aspectul de pana acum al unei interfete grafice AWT era oarecum relativ -

redimensionarea ferestrei putand modifica intreaga dispunere in fereastra . Aceasta

maleabilitate a interfetei grafice apare in Java datorita posibilitatii sale de a rula pe

diferite platforme care trateaza diferit elementele componente ale unei interfete

grafice .

Pentru a introduce un control mai strict asupra aspectului interfetei noastre Java ne

pune la dispozitie pentru pachetul AWT un numar de 5 administratori de dispunere .

DISPUNEREA COMPONENTELOR UNEI INTERFETE

Un administrator de dispunere determina modul in care vor fi aranjate componentele

unui contatiner . Administratorul implicit al Java este clasa FlowLayout . Ea permite

dispunerea secventiala a obiectelor , de la stanga la dreapta si de sus in jos .

Pachetul AWT poate folosi inca patru administratori : GridLayout , BorderLayout ,

CardLayout si GridBagLayout .

Pentru a crea un administrator pentru un container se creaza o instanta a clasei

container folosind o instructiune de tipul :

FlowLayout administrator=new FlowLayout();

Acest administrator nou creat trebuie apoi declarat ca administrator pentru container

cu ajutorul metodei setLayout() . Administratorul de dispunere trebuie stabilit inainte

de a adauga componente containerului . Daca nu este stabilit un administrator explicit

atunci apare automat cel de dispunere secventiala ( FlowLayout ) .

In exemplul de mai jos avem inceputul unui applet care foloseste un administrator de

dispunere :

public class Inceput extends java.applet.Applet {

FlowLayout ad=new FlowLayout();

public void init() {

setLayout(ad);

}

}

ADMINISTRATORUL DE DISPUNERE SECVENTIALA ( FlowLayout )

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

- 107 -

Page 108: Programare Java

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

- 108 -

Page 109: Programare Java

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

- 109 -

Page 110: Programare Java

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 :

- 110 -

Page 111: Programare Java

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

}

}

}

- 111 -

Page 112: Programare Java

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,1 1,1

0,2 1,2

Nume

Parola

OK

Nume

Parola

OK

- 112 -

Page 113: Programare Java

- 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

- 113 -

Page 114: Programare Java

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

- 114 -

Page 115: Programare Java

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 .

- 115 -

Page 116: Programare Java

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

- 116 -

Page 117: Programare Java

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;

}

- 117 -

Page 118: Programare Java

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

- 118 -

Page 119: Programare Java

Numar de clicuri : 2

Numar de clicuri : 3

3. Miscarile mouseului

AWT defineste doua tipuri distincte de miscari ale mouseului : tragerea sa - miscarea

se face cu butonul semnificativ apasat , si miscarea simpla - cu butonul neapasat .

Evenimentele de mai sus sunt interceptate si tratate cu ajutorul metodelor

mouseDrag() si mouseMove() .

Metoda mouseMove() seamana mult cu metodele care tratau clicurile de mouse :

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

...

}

Meotda mouseDrag() are o semnatura similara si mai trebuie sa mentionam ca in

ambele metode argumentele pentru coordonatele x si y reprezinta noua pozitie a

mouseului si nu cea initiala .

Metodele mouseEnter() si mouseExit() sunt apelate cand mouseul patrunde sau

paraseste un applet sau o portiune a acestuia . Ambele metode au semnaturi similare

cu cele intalnite mai inainte , coordonatele x si y referindu-se aici la 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);

}

- 119 -

Page 120: Programare Java

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

}

}

- 120 -

Page 121: Programare Java

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.

- 121 -

Page 122: Programare Java

Programare Java

Curs – 11

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

- 122 -

Page 123: Programare Java

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 F11

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 :

- 123 -

Page 124: Programare Java

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 .

- 124 -

Page 125: Programare Java

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

/...

}

- 125 -

Page 126: Programare Java

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

- 126 -

Page 127: Programare Java

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

- 127 -

Page 128: Programare Java

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

- 128 -

Page 129: Programare Java

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 .

- 129 -

Page 130: Programare Java

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 .

- 130 -

Page 131: Programare Java

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

- 131 -

Page 132: Programare Java

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

}

}

- 132 -