Java Curs
Java Curs
Curs – 2
INSTRUCTIUNI SI EXPRESII
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;
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.
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.
Daca vrem sa cream mai multe variabile de acelasi tip le putem declara pe toate in aceeasi
instructiune, separate de “, “:
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.
- variabilele numerice: 0
- caracterele: “\0”
- variabilele booleene: false
- obiectele: null
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:
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.
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
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.
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.
idCod=8546;
imbracatRapid=false;
COMENTARII
Una dintre metodele cele mai importante de crestere a lizibilitatii unui program este
folosirea comentariilor.
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.
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;
double 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:
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). Deoarece 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:
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.
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.
OPERATII ARITMETICE
“+“ 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.
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.");
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));
}
}
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
X=20; Y=5;
X=X/Y+5; si
X/=Y+5;
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.
int X=7;
X=X++;
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.
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.
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 utilizati in Java:
== egal x==3
!= diferit x!=3
< mai mic decat x<3
> mai mare decat x>3
<= mai mic sau egal cu x<=3
>= mai mare sau egal cu x>=3
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.
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.
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:
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 “ + “ 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=numeleMeu + “ Jr.”;
Programare Java
Curs – 3
TABLOURI
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[];
String[] cuvinte;
Point[] lovituri;
int[] salariu;
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:
Deoarece tablourile sunt obiecte Java putem folosi operatorul new pentru a crea o
noua instanta a unui tablou:
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:
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.
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;
int lungime=lungime.length;
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];
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]
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: }
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.
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:
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.
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
}
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.
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”;
if (alegere==true)
if (alegere)
1: class TestParitate {
2:
3: void verificareParitate(int val) {
4: System.out.println(“Valoarea este “
5: +val+”. “);
6: if (val%2==0)
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: }
OPERATORUL CONDITIONAL
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;
int celMaiBunScor;
if (scorulMeu>scorulTau) celMaiBunScor=scorulMeu;
else celMaiBunScor=scorulTau;
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.
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”);
}
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”);
}
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);
}
}
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
In exemplul de mai jos putem vedea o instructiune for care atribuie tuturor pozitiilor
unui tablou String valoarea 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.
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 FOR-EACH
Pentru a exemplifica utilizarea practica vom studia pe scurt doua exemple de utilizare.
In codul sursa anterior declaram un tablou de elemente intregi si dam toata lista de
valori chiar de la declarare. Pentru a parcurge tabloul folosim apoi structura for-each.
Atentie – variabila i, de tipul intreg aici, NU ESTE tot timpul de acest tip, ca in cazul
unui index clasic al FOR-ului.
Dupa cum se poate vedea in exemplul anterior, in cazul in care manipulam cu FOR-
EACH un tablou de elemente de tip String (tabloul zile, mai exact) vom folosi si in
cadrul instructiunii o variabila de tip String pentru a parcurge acel tablou.
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).
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(“]”);
}
}
CICLURI DO … WHILE
Acest ciclu este foarte asemanator cu while – 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);
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.
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;
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.
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.
TRATATEA ERORILOR
Dezvoltand putin conceptul, exista mai multe variatiuni de utilizare a acestuia. Avem
posibilitatea de a intercepta, individual, cate o eroare pe care apoi sa o tratam tot
individual. Acest lucru duce la o sintaxa cu un bloc TRY si cel putin un bloc
CATCH.
try {
for (int i=0; i<=argumente.length; i++) System.out.println(arg[i]); //poate da o
exceptie daca nu exista argument
}
catch (ArrayIndexOutOfBoundsException exceptie)
{
System.out.println(“Ceva nu e bine - s-a 'prins' ceva eronat...");
}
In exemplul de mai sus, o utilizare clasica, se va produce o eroare din cauza ajungerii
variabilei i la o valoare mai mare decat numarul de elemente al tabloului denumit
argumente. Eroarea produsa este de tip ArrayIndexOutOfBoundsException. Pentru a
preintampina oprirea executiei programului printr-un mesaj de eroare standard si putin
lizibil, codul din blocul CATCH spune ca: in cazul in care apare o exceptie/eroare de
acel tip, se va executa codul sursa din blocul de instructiuni CATCH. In practica, in
loc de ilizibilul mesaj standard de eroare, programul va afisa textul droit de noi.
Exista si posibilitatea de a trata mai multe tipuri de erori in cadrul acestui concept. In
acest caz avem posibilitatea de a insera oricate blocuri CATCH dorim, fiecare
adresand o anumita eroare, ca in exemplul urmator:
try {
int numar=Integer.parseInt(sir);
System.out.println("Numarul introdus este: "+numar);
}
catch (ArrayIndexOutOfBoundsException exceptie)
{
System.out.println(“Ceva nu e bine - s-a 'prins' ceva eronat...");
}
catch (NumberFormatException exceptie) {
System.out.println("...nu s-a introdus un numar!");
}
Daca dorim sa tratam/interceptam mai multe erori cu ajutorul unui acelasi bloc de
instructiuni, putem cupla tipurile de erori ca in sintaxa urmatoare:
try {
int numar=Integer.parseInt(sir);
System.out.println("Numarul introdus este: "+numar);
}
catch (NumberFormatException | ArrayIndexOutOfBoundsException exceptie) {
System.out.println("..nu e numar sau ati deposit indexul!");
}
try {
for (int i=0; i<=argumente.length; i++) System.out.println(arg[i]);
}
catch (Exception exceptie)
{
System.out.println(“Am intalnit o eroare… nu conteaza care!");
}
try {
for (int i=0; i<=argumente.length; i++) System.out.println(arg[i]);
}
catch (Exception exceptie)
{
System.out.println(“Am intalnit o eroare… nu conteaza care!");
}
finally
{
System.out.print("ASTA SE EXECUTA TOTDEAUNA.");
}
Programare Java
Curs – 4
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.
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.
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
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.
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 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:
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 {}
class Persoana {
String culoare;
String sex;
boolean flamand; }
void hranescPersoana() {
if (flamand==true) {
System.out.println(“Bun – foame!”);
Flamand=false;
} else
System.out.println(“Nu merci – am mancat!”);
}
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”);
}
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.
1. Cream, separat, un applet sau o aplicatie java care sa foloseasca aceasta clasa
2. adaugam metoda main() in listingul nostru
class Persoana {
String culoare;
String sex;
boolean flamand;
void hranescPersoana() {
if (flamand==true) {
System.out.println("Bun - vrea mancare");
flamand=false; }
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");
}
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.
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.
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.
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.
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).
Incepand cu Java8, interfetele au posibilitatea de a declara si codul sursa in cadrul
metodelor lor, declaratia acestor metode incepand prin utilizarea cuvantului cheie
default:
interface setMetode {
//interfata cu metode definite prin default, introduse in Java8. Inainte definitiile de
metode erau void si fara cod sursa, metoda trebuind suprascrisa in clasa de baza
default void metoda1(){
System.out.println("metoda1() din interfata setMetode");
}
default void metoda2(){
System.out.println("metoda2() din interfata setMetode");
}
}
PACHETE
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.
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.
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.
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.
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:
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.
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:
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:
In lipsa unui browser putem folosi pentru a vizualiza pagina noastra utilitarul
appletviewer din pachetul JDK, cu sintaxa:
appletviewer Palindrom.html
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:
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:
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.
GESTIONAREA MEMORIEI
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;
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:
clientulMeu.totalFactura.rezervat=true;
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.
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.
APELAREA METODELOR
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();
class VerificareSir {
METODE DE CLASA
Int pretMaxim=Math.max(primulPret,alDoileaPret);
String s,s2;
s=”articol”;
s2=s.valueOf(5);
s2=String.valueOf(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 paragrafele 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:
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 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.
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:
import java.awt.Point;
class DreptunghiulMeu {
int x1=0;
int y1=0;
int x2=0;
int y2=0;
void afisareDreptunghi() {
System.out.print(“Dreptunghiul meu: <”+x1+”, “+y1);
System.out.println(“, “+x2+”, “+y2+”>”);
}
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
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:
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.
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(“----“);
}
}
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:
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);
}
}
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.
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.
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:
De obicei exista doua motive pentru care se face suprascrierea unei metode
implementate deja de o superclasa:
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.
// 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);
}
// din AfisareSubClasa2
void afisareDate() {
super.afisareDate();
System.out.println(“Z este “+z);
}
SUPRASCRIEREA CONSTRUCTORILOR
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
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);
}
}
METODE DE FINALIZARE
Curs – 5
REFERINTE LA OBIECTE
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.
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:
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
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:
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.
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:
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 obiectelor
- gasirea clasei de care apartine un obiect
- testarea daca un obiect reprezinta o instanta a unei clase date
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.
In exemplul de mai jos este exemplificata aflarea clasei pentru un obiect atribuit variabilei obj:
String nume=obj.getClass().getName();
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:
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.
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. 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.
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
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:
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.
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:
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:
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:
CREAREA METODELOR
Metodele definesc comportamentul unui obiect – actiunile efectuate la crearea obiectului sau pe
parcursul duratei sale de viata.
DEFINIREA METODELOR
- 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 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:
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.
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];
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.
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:
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:
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 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.
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.
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:
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.
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 – 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.
Pentru a transmite argumente unui program Java acestea trebuie adaugate la executie dupa numele
programului:
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.
In continuare este prezentat un exemplu de aplicatie Java care returneaza numarul cel mai mare dintre
5 intregi, introduse una cate una ca parametrii :
import java.io.*;
public class Largest {
int j;
int[] x = new int[5]; // tablou cu 5 pozitii
void getLargest() throws IOException
{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String[] number = new String[10];
for(int i=0;i<5;i++)
{
System.out.println("Enter any number:");
number[i]=br.readLine();
x[i] = Integer.parseInt(number[i]);
}
for(j=0;j<4;j++)
{
if(x[j]>x[j+1]) x[j+1]=x[j];
}
System.out.println("The Largest number in a given array is:" +x[j]);
}
public static void main(String[] args) throws IOException {
Largest obj = new Largest();
obj.getLargest(); //apelul metodei getLargest()
}
}
******************************************************
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.
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, Opera, Maxthon etc. 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.
Incepand cu 2017 (Firefox) si sfarsitul lui 2016 (Chrome) applet-urile nu mai pot rula in mod normal
in aceste browsere, tehnologia NPAPI (Netscape Plugin Application Programming Interface) nu mai
este suportata (nu mai functioneaza nici Silverlight, FlashPlayer, AdobeAcrobat PlugIn, Shockwave
Player, Unity etc).
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 transfera 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.
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 care, desi au pierdut mult din cota de piata in
ultimii ani, detin in jur de minim 55% din piata indiferent conform carei publicatii de specialitate).
Microsoft a implementat si versiunile Java 1.1, 2 si mai noi dar implementarile mai produc anumite
surprize neplacute, in unele cazuri existand applet-uri care nu functioneaza corect in cazul programarii
lor folosind ultima versiune a limbajului.
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.
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:
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 a fost foarte importanta in problema securitatii; respectiva 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
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:
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.
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():
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():
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():
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():
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.
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:
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;
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.
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 ExpressionStudio sau Adobe 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>
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:
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
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:
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 etichetele <object> si <embed>.
Aceasta eticheta este folosita pentru toate obiectele – programe interactive sau alte elemente externe –
care pot fi prezente drept parte a unei pagini web.
- atributul code trebuie inlocuit cu classid; in plus, inainte de numele clasei applet-ului trebuie
specificat “java:”.
- eticheta <applet> se inlocuieste cu <object>
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:
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:
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:
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:
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: }
<html>
<head>
<title>Pagina noua cu palindrom</title>
</head>
<body>
<p>
Daca nu este specificata nici o valoare pentru parametrul palindrom textul implicit este “Dennis and
Edna sinned”.
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.
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:
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.
Putem, de asemenea, adauga intr-o arhiva Java alte fisiere folosind comanda:
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:
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.
Versiunile curente ale celor mai raspandite browser-e de pe piata suporta pe langa arhive JAR si
formate recunoscute pe scara larga ca ZIP sau CAB.
Exemplul de mai jos foloseste o arhiva ZIP:
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:
Curs – 6
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:
ecran.drawLine(185,80,222,80);
DREPTUNGHIURI
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
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.
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
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:
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:
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().
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:
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.
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:
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).
ecran.drawArc(20,25,315,150,5,-190);
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.
- 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
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
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.
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.
- numele fontului
- stilul fontului
- dimensiunea in puncte a fontului
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:
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:
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.
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:
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);
}
}
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.
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:
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.
- 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);
Din acest moment toate operatiile de desenare vor folosi aceasta culoare.
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.
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 introduse 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.
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.
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():
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.
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.
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.
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.
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():
Toate operatiile de desenare care vor urma pentru obiectul ecran2D vor folosi acest model de umplere.
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.
➔ Optiunea CAP_BUTT
➔ Optiunea CAP_ROUND
➔ Optiunea CAP_SQUARE
Stilurile de imbinare sunt JOIN_MITER (pentru imbinarea prin prelungirea muchiilor exterioare),
JOIN_ROUND (pentru imbinarea rotunjita) si JOIN_BEVEL (pentru o imbinare tesita).
Optiunea JOIN_ROUND
Exemplul de mai jos creaza un obiect BasicStroke si il stabilesc drept stil de tusa curent:
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.
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: coordonatele x, y ale unui
capat de segment si coordonatele x, y ale celuilalt capat:
Aceasta instructiune creeaza o linie intre punctele 60,5 si 13,28. Atentie la utilizarea literei f pentru
specificarea tipului float pentru argumente.
DREPTUNGHIURI
Dreptunghiurile sunt create folosind clasele Rectangle2D.Float sau Rectangle2D.Double. Diferenta intre
cele doua este tipul argumentelor.
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:
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:
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.
Metoda moveTo() a clasei GeneralPath este folosita pentru a crea primul punct al poligonului.
Urmatoarea instructiune poate fi folosita pentru a incepe de exemplu 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 punctul initial 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.
import java.awt.*;
import java.awt.geom.*;
Curs – 7
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.
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.
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.
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.
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 “periculosul” 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.*;
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; 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.
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.*;
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:
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:
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 ne facem probleme deocamdata 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:
ecran.drawImage(imagineInvizibila,0,0,this);
Pentru a elimina si umplerea ecranului cu culoarea de fond, operatia implicita a metodei update(), este indicat sa suprascriem
si metoda update() la modul urmator:
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.*;
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);
ecran.drawImage(imgInvizibila,0,0,this);
}
public void destroy() {
invizibil.dispose();
}
}
- 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:
- 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.
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:
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.
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:
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:
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:
Daca fisierul grafic trebuie afisat la o alta scara decat originalul trebuie sa folosim sase argumente pentru metoda
drawImage():
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 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.*;
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");
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.*;
AudioClip sunetFundal;
AudioClip bip;
Thread executabil;
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.
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.
Exista doar doi pasi care trebuie urmati pentru a adauga o componenta la un container:
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.*;
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 (o legenda) 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
- 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.*;
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.*;
CASETE DE VALIDARE
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.*;
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 conforma 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.*;
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:
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.*;
public class ListaSelectie extends java.applet.Applet {
Choice lista=new Choice();
Label eticheta=new Label("Echipa care credeti ca va castiga Europa League in 2012:");
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
Trebuie sa facem cateva observatii legate de unele metode prezentate in paragrafele de mai sus:
- metoda Checkbox(String,grup,boolean) se poate inlocui incepand cu 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 poate
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
- 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 ultim 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.*;
Clasa TextField are si ea cateva metode foarte des folosite pentru a controla campurile de text:
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.*;
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.
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.*;
Ca si in cazul celorlalte componente si listele derulante au cateva metode des utilizate in conjunctie cu
ele:
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
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.*;
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-ul urmator; acesta deseneaza o cruce in
centrul ferestrei Applet si poate muta centru acesteia daca fereastra care publica appletul este
redimensionata:
import java.awt.*;
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.
Curs JAVA
Această maleabilitate a interfeței grafice apare în Java datorita posibilității sale de a rula
pe diferite platforme care tratează diferit elementele componente ale unei interfețe
grafice.
Pentru a introduce un control mai strict asupra aspectului interfeței noastre, Java ne pune
la dispoziție pentru pachetul AWT un număr de 5 administratori de dispunere (layout
manager).
DISPUNEREA COMPONENTELOR UNEI INTERFEȚE
Un administrator de dispunere determină modul în care vor fi aranjate componentele
unui container. Administratorul implicit al Java este clasa FlowLayout. Ea permite
dispunerea secvențială a obiectelor, de la stânga la dreapta și de sus în jos.
frameObj.setSize(300, 300);
frameObj.setVisible(true);
}
public static void main(String argumente[])
{
new FlowLayoutExemplu();
}}
ADMINISTRATORUL DE DISPUNERE TABELARĂ
Pune componentele într-un tabel (rânduri si coloane). Componentele sunt adăugate
începând cu celula aflată cel mai în stânga pe primul rând și continuând spre dreapta. În
continuare se va trece la următoarea linie și tot așa mai departe.
Se pot utiliza încă doua argumente, care exprimă spațiul pe orizontală și pe verticală
între componente. Spațiul implicit între componentele administrate astfel este 0 pixeli pe
ambele direcții. ...dacă mai punem încă două argumente putem controla și spațiul pe
orizontală și pe verticală dintre componente ☺.
Atenție: componentele vor ocupa totdeauna întregul spațiu al celulei în care trebuie să se
integreze.
ADMINISTRATORUL DE DISPUNERE TABELARĂ
import java.awt.*;
import javax.swing.*;
public class GridLayoutExemplu {
JFrame frameObj;
GridLayoutExemplu() {
frameObj = new JFrame();
JButton btn1 = new JButton("1"); JButton btn2 = new JButton("2"); JButton btn3 = new JButton("3"); JButton btn4 = new JButton("4"); JButton btn5 = new JButton("5");
JButton btn6 = new JButton("6"); JButton btn7 = new JButton("7"); JButton btn8 = new JButton("8"); JButton btn9 = new JButton("9");
// adding buttons to the frame
// since, we are using the parameterless constructor, therefore;
// the number of columns is equal to the number of buttons we
// are adding to the frame. The row count remains one.
frameObj.add(btn1); frameObj.add(btn2); frameObj.add(btn3); frameObj.add(btn4); frameObj.add(btn5);
frameObj.add(btn6); frameObj.add(btn7); frameObj.add(btn8); frameObj.add(btn9);
frameObj.setLayout(new GridLayout(3, 3, 20, 25)); // un tabel cu 3x3 celule, spatiu pe orizontala 20 si pe verticala 25
frameObj.setSize(300, 300); frameObj.setVisible(true);
}
public static void main(String argumente[]) {
new GridLayoutExemplu();
}
}
ADMINISTRATORUL DE DISPUNERE MARGINALĂ
BorderLayout împarte fereastra astfel:
Sunt două variante principale ale constructorului BorderLayout: fără niciun parametru
sau cu 2 parametri. Prima varianta creează o dispunere fără spațiere între componente
iar a doua specifică distanta în pixeli (orizontală/verticală) între componente. Adăugarea
componentelor la container se face cu o metodă de tipul:
add(componenta, pozitie);
Primul argument este componenta care trebuie adaugata iar al doilea este:
"BorderLayout.CENTER", "BorderLayout.NORTH", "BorderLayout.SOUTH",
"BorderLayout.EAST" și "BorderLayout.WEST".
ADMINISTRATORUL DE DISPUNERE MARGINALĂ
În cazul în care add() din clasa JFrame este folosită fără a specifica o regiune va fi
adăugată numai ultima componentă (toate celelalte anterioare nu mai apar ☺), iar
această componentă acoperă toată zona.
În mod normal, acest administrator folosește un panou pentru fiecare card. Mai întâi se
introduc componentele în panouri și apoi acestea se introduc în containerul de bază
pentru care s-a stabilit o dispunere în stivă.
add(string, container);
Primul argument este un sir care reprezintă numele cardului. Al doilea argument este
containerul sau componenta care reprezintă cardul. Daca este un container, acesta
trebuie să conțină deja toate componentele necesare lui.
• public void next(Container parent) -> pentru aducerea următorului card din container
• public void previous(Container parent) -> pentru aducerea precedentului card din
container
• public void first(Container parent) -> pentru aducerea primului card din container
• public void last(Container parent) -> pentru aducerea ultimului card din container
• public void show(Container parent, String name) -> pentru aducerea card-ului
specificat prin nume
public CardLayoutExemplu() {
JPanel jPanel1 = new JPanel(); JPanel jPanel2 = new JPanel(); JPanel jPanel3 = new JPanel(); JPanel jPanel4 = new JPanel();
JLabel jLabel1 = new JLabel("C1"); JLabel jLabel2 = new JLabel("C2"); JLabel jLabel3 = new JLabel("C3"); JLabel jLabel4 = new JLabel("C4");
JButton firstButton = new JButton(„First"); JButton nextButton = new JButton("->"); JButton previousButton = new JButton("<-"); JButton lastButton = new JButton(„Last");
nextButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { if (currCard < 4) {currCard = currCard + 1; cObjl.show(cPanel, "" + (currCard)); } } });
previousButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { if (currCard > 1) {currCard = currCard - 1; cObjl.show(cPanel, "" + (currCard)); } } });
getContentPane().add(cPanel, BorderLayout.NORTH);
getContentPane().add(btnPanel, BorderLayout.SOUTH);
cll.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
cll.setVisible(true); } }
ADMINISTRATORUL DE DISPUNERE TABELARĂ NEPROPORȚIONALĂ
E o extensie a dispunerii tabelare. Exista câteva diferențe:
• o componentă poate ocupa mai multe celule ale tabelului
• proporțiile între diferitele rânduri sau coloane nu trebuie să fie aceleași
• componentele dispuse în cadrul celulelor pot fi aranjate în diferite moduri
Pentru a determina spațiul lăsat în jurul unui panou putem folosi inserțiile (insets). Clasa
Insets conține valori pentru inserțiile din partea de sus, de jos, din stânga și din dreapta,
valori folosite la desenarea panoului. Inserțiile determina spațiul dintre marginile
panoului și componentele acestuia.
Pentru a modifica inserțiile trebuie suprascrisă metoda Insets() sau metoda getInsets() -
ambele metode realizând același lucru.
Se creează un nou obiect Insets unde constructorul clasei primește ca argumente patru
valori întregi: inserțiile pentru partea de sus, din stanga, de jos și din dreapta panoului.
Metoda returnează apoi obiectul Insets.
public Insets getInsets() {
return new Insets(10,30,10,30);}
ADMINISTRATORUL DE DISPUNERE TABELARĂ NEPROPORȚIONALĂ
import java.awt.Button;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import javax.swing.*;
public GridBagLayoutExample() {
setLayout(grid);
this.setLayout(layout);
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 0; gbc.gridy = 0;
gbc.gridx = 1; gbc.gridy = 0;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridx = 1; gbc.gridy = 1;
gbc.gridx = 0; gbc.gridy = 2;
gbc.fill = GridBagConstraints.HORIZONTAL;
gbc.gridwidth = 2;
setDefaultCloseOperation(EXIT_ON_CLOSE); } }
ADMINISTRATORII DE DISPUNERE
• BoxLayout
• GroupLayout
• ScrollPanelLayout
• SpringLayout
INTERACȚIUNEA CU UTILIZATORUL. EVENIMENTE.
Schimbarea stării unui obiecte se numește eveniment. Click pe un buton, tragerea cu
mouse-ul, apăsarea unei taste etc. sunt evenimente.
Pachetul java.awt.event conține mai multe clase dedicate și interfețe „de ascultare”
(Listener) pentru tratarea evenimentelor.
INTERACȚIUNEA CU UTILIZATORUL. EVENIMENTE.
Interfață are 5 metode cu care lucrăm (le suprascriem când avem nevoie ☺):
1) public abstract void mouseClicked(MouseEvent e);
2) public abstract void mouseEntered(MouseEvent e);
3) public abstract void mouseExited(MouseEvent e);
4) public abstract void mousePressed(MouseEvent e);
5) public abstract void mouseReleased(MouseEvent e);
INTERACȚIUNEA CU UTILIZATORUL. EVENIMENTE MOUSE.
import java.awt.*; import java.awt.event.*;
public class Ex_MouseListener extends Frame implements MouseListener{
Label l;
Ex_MouseListener(){
addMouseListener(this);
l=new Label(); l.setBounds(20,50,300,20); add(l);
setSize(300,300); setLayout(null); setVisible(true); }
public void mouseClicked(MouseEvent e) { l.setText("Click de mouse"); }
public void mouseEntered(MouseEvent e) { l.setText("Intrare mouse pe suprafata");}
public void mouseExited(MouseEvent e) { l.setText("Iesire mouse de pe suprafata");}
public void mousePressed(MouseEvent e) { l.setText("Mouse apasat");}
public void mouseReleased(MouseEvent e) { l.setText("Mouse eliberat");}
public static void main(String[] args) {
new Ex_MouseListener();
}
}
INTERACȚIUNEA CU UTILIZATORUL. EVENIMENTE MOUSE.
import java.awt.*; import java.awt.event.*;
public class Ex_MouseListenerCuGrafica extends Frame implements MouseListener{
int puncte=0;
Ex_MouseListenerCuGrafica(){
addMouseListener(this); setSize(300,300); setLayout(null); setVisible(true); }
public void mouseClicked(MouseEvent e) {
Graphics g=getGraphics();
g.setColor(Color.ORANGE); g.fillOval(e.getX(),e.getY(),20,20);
g.setColor(Color.RED); puncte++; g.drawString("Punct "+puncte,e.getX(),e.getY()+6); }
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
public void mousePressed(MouseEvent e) {}
public void mouseReleased(MouseEvent e) {}
public static void main(String[] args) {
new Ex_MouseListenerCuGrafica();
}}
INTERACȚIUNEA CU UTILIZATORUL. EVENIMENTE MOUSE.
Schimbarea poziției cursorului mouse-ului relativ la suprafață este tot un eveniment ☺.
Ne referim aici la mutarea (move) sau tragerea (drag) cursorului.
Interfața pentru tratarea acestor evenimente este MouseMotionListener, ce utilizează tot
un obiect MouseEvent.
JavaFX.
2021, Alexandru Tăbușcă, conf.univ.dr - diapozitiv 2
APLICAȚII RIA
RIA = Rich Internet Applications
Dezvoltat inițial de Chris Oliver (pentru compania See Beyond Technology Corporation,
preluată în 2005 de Sun Microsystems) sub numele F3 (Forms Follows Function)
• în 2005 Sun redenumește F3 în JavaFX
• în 2007 JavaFX este lansat oficial
• în 2008 NetBeans integrează JavaFX
• în 2009 Oracle achiziționează Sun și este lansat JavaFX 1.2
• în 2014 este lansată varianta JavaFX 8
Începând cu Java8, JDK include librăria JavaFX 8 cu modificări importante: suport special
pentru grafică 3D, suport pentru senzori, suport MathML, suport rich-text printing.
APLICAȚII RIA
Istoric JavaFX
Din Java11 s-a renunțat la integrare, JavaFX fiind disponibil ca descărcare separată.
JavaFX este acum oficial întreținut și organizat de Gluon, ca modul descărcabil pentru JDK.
✓ JavaFX este o librărie utilizată pentru a dezvolta RIA. Aplicațiile bazate pe JavaFX pot
rula multi-platformă, pe PC/telefoane mobile/TV-uri/tablete/MediaPlayer etc.
✓ JavaFX este o variantă mai nouă si mai actuală pentru dezvoltarea de interfețe grafice
pentru utilizatori (îmbunătățind clasicele AWT sau SWING).
✓ JavaFX conține un set bogat de API-uri pentru media și grafica, putând utiliza GPU-ul
pentru grafica accelerată hardware.
✓ JavaFX poate utiliza atât controale UI, Media, Web, 2D, 3D etc. incluse în această
librărie, cât și capabilitățile existente anterior in Swing.
JavaFX. CARACTERISTICI DE BAZĂ
✓ Scrisă în Java - disponibilă în orice limbaj executabil prin JVM (Java, Kotlin, Jruby etc.).
✓ FXML – JavaFX conține un limbaj numit FXML. Scopul acestuia este doar de a defini o
interfață cu utilizatorul, din punct de vedere vizual, apelând la sintaxa tip CSS
✓ Interoperabilitate Swing – în aplicație JavaFX putem avea conținut Swing, prin clasa
SwingNode. Astfel putem doar actualiza o aplicație Swing cu elemente JavaFX ☺.
✓ Stiluri tip CSS – JavaFX utilizează pentru design grafic comenzi tip CSS, lucru care
asigură un avantaj celor care deja cunosc CSS
✓ API Printing & Canvas – pachetul javafx.scene.canvas are clase pentru canvas, cu care
putem desena direct pe o suprafață din scena JavaFX. Pachetul javafx.print are clase
pentru diverse funcții legate de tipărire
✓ Librărie grafică integrată – JavaFX conține atât clase pentru grafica 2D cât și 3D
✓ javafx.application -> are clase responsabile pentru ciclul de viață al aplicațiilor JavaFX
✓ javafx.geometry -> clase pentru obiecte 2D și pentru a realiza diverse operații cu ele
✓ javafx.stage -> clase “container” de nivel înalt, unde se “desfășoară” aplicațiile JavaFX
JavaFX. API
✓ javafx.scene -> acest pachet conține clase și interfețe pentru scena grafică. Conține
totodată și sub-pachete precum: canvas, chart, control, effect, image, input, layout,
media, paint, shape, text, transform, web etc.
Nodurile unei scene pot avea aplicate efecte: opacitate, transformări, manipulatori de
evenimente, stări specifice ale aplicațiilor etc..
JavaFX. PRISM
Este o tehnologie de utilizare a accelerării grafice hardware care se bazează, pentru
redare, pe:
➢ GWT
Glass Windowing Toolkit – asigură servicii pentru managementul ferestrelor, timer-elor,
suprafețelor și cozilor de evenimente. GWT conectează platforma JavaFX la sistemul de
operare nativ pe care se rulează aplicația.
➢ QUANTUM TOOLKIT
Este un strat abstractizat care combină componentele de nivel „scăzut” (low-level) Prism,
Glass, Media Engine, Web Engine. Face legătura între Prism și GWT și le pune la
dispoziția JavaFX.
JavaFX. WEBVIEW
JavaFX poate insera conținut HTML într-o scenă grafică. WebView este componenta care
face acest lucru. Tehnologia pe care se bazează este WebKit, un motor de browser open-
source (folosit de exemplu de Safari). Suporta diverse tehnologii: HTML5, CSS, JavaScript,
DOM sau SVG.
Prin intermediul WebView avem posibilități de a:
• Reda conținut HTML local sau remote
• Suporta istoric de browsing (navigare Back/Forward)
• Reîncărca un conținut HTML
• Aplica efecte pe componentele web
• Edita conținut HTML
• Executa comenzi JavaScript
• Trata evenimente
…pe scurt, cu ajutorul WebView putem controla conținut web „pur” din Java ☺.
JavaFX. MEDIA ENGINE
1. STAGE
Este fereastra ce conține toate obiectele aplicației JavaFX. Se folosește clasa Stage din
pachetul javafx.stage. Obiectul Stage creat se dă ca argument metodei start() a clasei
Application.
Un obiect Stage are doi parametrii numiți width și height și este împărțit în două
secțiuni: conținut și decorațiuni (Title Bar și Borders)
Clasa Application
Face parte din pachetul javafx.application și este punctul de „intrare” al unei aplicații
JavaFX. Pentru a crea o aplicație vom “moșteni” de fiecare dată aceasta clasă ☺.
Vom suprascrie metoda start() și vom scrie în ea codul-sursă pentru aplicația JavaFX.
@Override
public void start(Stage scenaPrimara) throws Exception {
/*
Cod aplicatie JavaFX.
*/
}
}
Crearea unei aplicații JavaFX
În metoda start(), pentru o aplicație JavaFX tipică, trebuie urmați pașii de mai jos:
• Pregătim fereastra Stage și adăugăm Scene la Stage, apoi afișăm conținutul din Stage
primaryStage.setScene(scena1);
primaryStage.show();
Crearea unei aplicații JavaFX
1. Pregătirea Scene Graph
Avem nevoie de un nod root, ce poate fi de tip: Group, Region sau WebView.
a) Group
Group root = new Group()
Putem adăuga noduri la grup și prin utilizarea lor încă din constructorul Group:
Group root = new Group(Nod)
Crearea unei aplicații JavaFX
1. Pregătirea Scene Graph
b) Region
Este clasa de baza pentru controalele UI de tip:
Chart – clasa aparține de javafx.scene.chart, având două subclase PieChart și XYChart,
acestea având la rândul lor subclasele AreaChart, BarChart, BubbleChart etc.
Pane – este clasa bază a administratorilor AnchorPane, BorderPane, DialogPane etc. Face
parte din pachetul javafx.scene.layout
Control – este clasa bază a controalelor UI Accordion, ButtonBar, ChoiceBox,
ComboBoxBase, HTMLEditor etc. Face parte din pachetul javafx.scene.control
Putem instanția și într-un Group oricare dintre aceste clase și apoi utiliza instanța ca root.
StackPane panou = new StackPane(); //creare obiect StackPane
ObservableList lista = panou.getChildren(); //Adaugarea unui nod-copil la obiectul StackPane
lista.add(obiectNod);
Crearea unei aplicații JavaFX
1. Pregătirea Scene Graph
c) WebView
Acest tip de nod controlează motorul web și afișează conținut web.
Aceasta reprezintă containerul principal (exterior) și realizează fereastra de lucru pentru orice aplicație
JavaFX. Clasa Stage face parte din pachetul javafx.stage. Un obiect Stage este folosit ca parametru pentru
metoda start() a clasei Application.
Operațiile de baza pentru un obiect Stage sunt:
• Setarea titlului ferestrei
primaryStage.setTitle(“Aplicatie exemplu");
Există și metoda statică launch() pentru a lansa aplicația JavaFX. Din moment ce e o
metodă statică, trebuie apelata dintr-un context static – în general metoda main(). La
lansarea unei aplicații JavaFX se întâmplă următoarele:
Forme 2D în JavaFX.
2021, Alexandru Tăbușcă, conf.univ.dr - diapozitiv 2
Forme 2D în JavaFX
1. Linia, dreptunghiul, cercul, elipsa, poligonul, linia frântă, curba pătratică, arcul de cerc
2. Elemente care pot fi cuplate într-o ”cale”: mișcarea către o poziție nouă, linia, linia
orizontală, linia verticală, curbe cvadratice, arce
3. Putem desena preluând (prin “parsing”) căi clasice de tip SVG
Fiecare element de mai sus este reprezentat de o clasă din pachetul javafx.scene.shape.
Clasa Shape este clasă de bază pentru toate formele 2D din JavaFX.
Crearea unei forme 2D
Acest lucru presupune 3 pași conceptuali:
a) Instanțierea clasei necesare formei respective
Line linie = new Line();
Pentru a desena trebuie date valori acestor proprietăți, fie direct prin constructorul clasei:
Line linie = new Line(startX, startY, endX, endY)
fie prin folosirea metodelor dedicate de setare pentru aceste proprietăți:
setStartX(valoare), setStartY(valoare), setEndX(valoare), setEndY(valoare)
Clasele aferente elementelor 2D în JavaFX
Dreptunghi
Putem da valori și ultimelor doua proprietăți fie direct în constructor, fie prin metodele de
setare:
setArcWidth(valoare), setArcHeight(valoare)
Clasele aferente elementelor 2D în JavaFX
Cerc
radiusX
Putem da valori fie în constructor:
Ellipse elipsa = new Ellipse(centerX, centerY, radiusX, radiusY);
Metoda addAll() poate fi folosita și ulterior, pentru adaugarea câte unui punct individual.
Clasele aferente elementelor 2D în JavaFX
Curba pătratică Bezier
Este necesar acest element când trebuie o formă mai complexă decât cele clasice 2D.
Clasa relevanta este Path și are o listă de elemente predefinite (clase) pe care le poate
agrega în interiorul său:
• MoveTo
• LineTo
• HlineTo
• VlineTo
• ArcTo
• QuadCurveTo
• CubicCurveTo
Clasele aferente elementelor 2D în JavaFX
Cale de desenare
Clasa MoveTo necesită doi parametrii, X și Y, pentru punctul unde vrem să se ”mute”
cursorul de desenare. Putem să îi utilizăm în constructor:
MoveTo mutare = new MoveTo(100,100);
Clasa LineTo primește tot doi parametrii, X și Y, pentru punctul până la care dorim să se
tragă o linie, pornind de la punctul curent al cursorului de desenare:
LineTo liniecatre1 = new LineTo(200,200);
Clasele aferente elementelor 2D în JavaFX
Cale de desenare
Clasa HLineTo necesită un parametru, X, pentru desenarea unei linii orizontale intre
punctul curent și noua valoare pe orizontală. Putem să îl utilizăm în constructor:
HLineTo linieorizontala = new HLineTo (500);
Clasa VLineTo primește tot un parametru, Y, pentru desenarea unei linii verticale între
punctul curent și noua valoare pe verticală. Putem să îl utilizăm în constructor:
VLineTo linieverticala = new VLineTo (400);
Clasa ArcTo necesită 4 parametrii, pentru coordonatele X și Y ale centrului elipsei din care
face parte arcul, raza pe orizontală și respectiv pe verticală ale elipsei.
Putem sa îi utilizăm în constructor:
ArcTo arcTo1 = new ArcTo(x, y, radiusX, radiusY);
JavaFX dă posibilitatea de a se seta diverse proprietăți pentru obiectele sale de tip 2D:
✓ StrokeType
✓ StrokeWidth
✓ Fill
✓ Stroke
✓ StrokeLineJoin
✓ StrokeMiterLimit
✓ StrokeLineCap
✓ Smooth
Proprietăți ale obiectelor 2D
StrokeType reprezintă poziția marginii aplicate unei forme desenate. Se poate seta cu
ajutorul setStrokeType(), cu unul dintre parametrii:
• Inside – marginea se desenează în interiorul formei
• Outside – marginea se desenează în exteriorul formei
• Centered – (implicit) marginea se desenează încât mijlocul ei coincide cu linia ce
delimitează forma
Proprietăți ale obiectelor 2D
StrokeWidth reprezintă lățimea marginii aplicate unei forme desenate. Se poate seta cu
ajutorul setStrokeWidth(), cu valoare în pixeli.
Proprietăți ale obiectelor 2D
Path.setFill(COLOR.BLUE);
Proprietăți ale obiectelor 2D
Path.setStroke(COLOR.RED);
Proprietăți ale obiectelor 2D
Operațiuni cu obiecte și
imagini în JavaFX
2021, Alexandru Tăbușcă, conf.univ.dr - diapozitiv 2
Operațiuni cu obiectelor 2D în JavaFX
Putem executa următoarele operațiuni principale cu obiectele 2D în JavaFX:
1) Operații de combinare
• Uniune
• Intersecție
• Scădere
2) Transformări
• Deformare
• Rotație
• Scalare
• Translație
3) Tranziții (animații)
Operațiuni cu obiectelor 2D în JavaFX
1) Operații de combinare
• Uniune
• Intersecție
• Scădere
Daca adăugam mai mult de o forma la un grup atunci peste prima se poate suprapune
urmatoarea – in diverse moduri ☺.
Operațiuni cu obiectelor 2D în JavaFX
1) Operații de combinare
• Uniune
Operațiunea preia două (sau mai multe) forme și returnează zona ocupată de ele
combinate.
Metoda union() este o metodă de clasă, deci poate fi apelată având în stanga ei clasa
Shape, o subclasă sau un obiect de clasele respective.
Operațiuni cu obiectelor 2D în JavaFX
1) Operații de combinare
• Intersecție
Metoda intersect() este o metodă de clasă, deci poate fi apelată având în stanga ei clasa
Shape, o subclasă sau un obiect de clasele respective.
Operațiuni cu obiectelor 2D în JavaFX
1) Operații de combinare
• Scădere
Operațiunea preia (minim) 2 forme și returnează zona primei forme EXCLUZÂND zona pe
care se suprapune cu cealaltă/celelalte forme.
Metoda subtract() este o metodă de clasă, deci poate fi apelată având în stanga ei clasa
Shape, o subclasă sau un obiect de clasele respective.
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
“Transformare” înseamnă modificarea unor elemente grafice prin aplicarea unor reguli. În
JavaFX avem mai multe astfel de operațiuni des folosite:
• Deformarea
• Rotația
• Scalarea
• Translația
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
• Deformarea (EN: shearing sau skewing)
Aceasta are două variante care se referă la modificarea pe axele OX și respectiv OY.
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
• Deformarea (EN: shearing sau skewing)
În practică trebuie creat un obiect care va “conține” deformarea, apoi acesta este aplicat
unui obiect (o formă geometrică)
Shear deformareX = new Shear();
deformareX.setPivotX(200);
deformareX.setPivotY(250);
deformareX.setX(0.3);
deformareX.setY(0.0);
forma.getTransforms().addAll(deformareX);
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
• Deformarea (EN: shearing sau skewing)
În practică trebuie creat un obiect care va “conține” deformarea, apoi acesta este aplicat
unui obiect (o formă geometrică)
Shear deformareY = new Shear();
deformareY.setPivotX(600);
deformareY.setPivotY(80);
deformareY.setX(0.0);
deformareY.setY(0.2);
forma.getTransforms().addAll(deformareY);
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
• Rotația
Se utilizează clasa Rotate pentru a defini rotația, apoi se aplică unui obiect.
forma.getTransforms().addAll(rotatie);
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
• Scalare
În acest caz modificăm dimensiunile generale ale unei forme. Practic, multiplicăm cu un
anumit factor dimensiunile originale.
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
• Scalare
Se utilizează clasa Scale, se configurează un obiect de acest tip și se aplică unei forme.
cerc1.getTransforms().addAll(scalare);
Operațiuni cu obiectelor 2D în JavaFX
2) Transformări
• Translație
Se utilizează clasa Translate, se configurează un obiect de acest tip și se aplică unei forme.
cerc1.getTransforms().addAll(translatie);
Operațiuni cu obiectelor 2D în JavaFX
3) Tranziții (animații)
Animația unui obiect înseamnă crearea iluziei “mișcării” prin (re)desenări succesive, la
viteze mari.
Animațiile disponibile direct în JavaFX sunt: Fade Transition, Fill Transition, Rotate
Transition, Scale Transition, Stroke Transition, Translate Transition, Path Transition,
Sequential Transition, Pause Transition, Parallel Transition etc.
Operațiuni cu obiectelor 2D în JavaFX
3) Tranziții (animații)
Toate tipurile de tranziții anterioare sunt implementate prin clase individuale, parte a
pachetului javafx.animation.
//varianta 1
FileInputStream inputstream1 = new FileInputStream("C:\\imagini\\poza1.jpg");
Image imagine1 = new Image(inputstream1);
//varianta 2
Image imagine2 = new Image(new FileInputStream(“http://www.a.ro/poze/poza2.jpg”));
Imagini externe în JavaFX
După încărcarea imaginii într-un obiect Image putem să o afișăm cu ajutorul clasei
ImageView.
ImageView imagineAfisare = new ImageView(imagine)
Bineînțeles, putem folosi oricâte obiecte ImageView dorim, inclusiv bazate pe aceeasi
imagine “sursă”.
Pentru obiectul de tip ImageView există cateva metode des folosite:
• setX() și setY() -> stabilesc exact coordonatele de unde va începe afișarea imaginii
• setFitHeight() și setFitWidth() -> stabilesc la ce dimensiuni dorim să afișăm imaginea
• setPreserveRation() -> primește valoare true sau false și se referă la păstrarea/nu a
aspectului
• getWidth() și getHeight() -> pentru a afla ce dimensiuni are imaginea încărcată într-un
obiect
Imagini externe în JavaFX
Pentru un control mai exact asupra imaginilor JavaFX conține clasele PixelReader și
PixelWriter, folosibile pentru a citi/scrie direct pixeli – creând astfel un obiect de tip
WritableImage. Putem citi, modifica și apoi scrie la nivel de pixel.
Forme 3D &
Evenimente
2021, Alexandru Tăbușcă, conf.univ.dr - diapozitiv 2
JavaFX – forme 3D
Am prezentat și utilizat anterior forme 2D, pe un plan XY. JavaFX poate utiliza și forme 3D,
în plan XYZ.
Formele utilizate:
• Cilindru (Cylinder)
• Sferă (Sphere)
• Cutie (Box)
Fiecare formă are o clasă corespondentă, din pachetul javafx.scene.shape, toate
moștenind clasa Shape3D de acolo. Pentru a utiliza o astfel de clasă/formă, avem de făcut
3 pași conceptuali:
1. instanțiere obiect de clasă corespondentă
2. setarea proprietăților obiectului
3. adăugarea obiectului la un grup
JavaFX – forme 3D
Pasul 1
Instanțiere obiect de clasă corespondentă. Se face extrem de simplu, pe baza
constructorilor standard:
cutie.setWidth(200.0);
cutie.setHeight(400.0);
cutie.setDepth(200.0);
JavaFX – forme 3D
Pasul 3
Adăugarea obiectului la un grup. Acest lucru se face utilizându-l ca parametru pentru
constructorul grupului, sau prin adăugare ulterioară la un grup:
1. CullFace -> nu se vor mai desena părțile formei care nu sunt oricum vizibile
2. DrawMode -> putem controla tipul de desenare (contur sau plin)
3. Material -> putem controla materialul ce se va vedea pe suprafața formei
JavaFX – forme 3D. Proprietatea CullFace.
Nu se vor mai desena fețele (poligoanele) formei care nu sunt oricum vizibile. Metoda
utilizată pentru manipularea acestei proprietăți este setCullFace. Există trei posibilități de
setare:
- setCullFace(CullFace.NONE) -> nu este ignorată nicio față la desenare
- setCullFace(CullFace.FRONT) -> ignoră fețele care sunt îndreptate spre prim-plan
- setCullFace(CullFace.BACK) -> ignoră fețele care sunt îndreptate spre spate
Obs. Phong este un celebru expert în grafică video vietnamez, care a inventat o metodă
de interpolare folosită pentru umbrirea (shading) suprafețelor. Tehnica sa este în general
comparată cu cea a lui Gouraud.
JavaFX – forme 3D. Proprietatea Material.
Proprietățile unui obiect PhongMaterial:
- bumpMap -> este o hartă de acoperire stocată ca imagine RGB (se obține din PhotoShop cu
filtre 3D sau din Poser etc.)
- diffuseMap -> este o hartă de acoperire cu o culoare difuză
- selfIlluminationMap -> este o hartă cu iluminarea suprafeței din interior
- specularMap -> este o hartă de acoperire speculară (oglindire a exteriorului pe suprafața 3D)
- diffuseColor -> este o culoare difuză
- specularColor -> este o culoare cu reflexie speculară
- specularPower -> puterea speculară (cu care se reflectă ceva pe suprafața 3D)
Implicit, o formă 3D este acoperită cu un obiect de tip PhongMaterial cu proprietatea
diffuseColor pe nuanța gri.
JavaFX – forme 3D. Proprietatea Material.
Exemplu:
bumpMap
diffuseMap
selfIllumination
specularMap
diffuseColor
specularColor
specularPower
JavaFX – Evenimente.
Evenimente JavaFX (ca de altfel și cele folosite în scenariile anterioare) sunt produse de
orice apăsare de buton, mișcare a mouse-ului, apăsarea unei taste, selectarea unui
element dintr-o listă, mutarea barei de derulare etc.
Evenimentele JavaFX se împart în general în două categorii:
1. Evenimente de prim-plan (foreground events) -> sunt evenimente care necesită o
interacțiune directă a unui utilizator cu interfața grafică. De exemplu: apăsarea unui
buton, mutarea mouse-ului, apăsarea unei taste, selectarea unui element din listă,
derularea etc.
2. Evenimente în fundal (background events) -> nu necesită interacțiunea directă a
utilizatorului. De exemplu: întreruperile la nivel de SO, erori de componente
hardware/software, expirarea unor timer-e, încheierea unor operațiuni/procese etc.
JavaFX – Evenimente.
Evenimentele cele mai des utilizate:
- Mouse Event -> apare la apăsarea unui buton de mouse. Este reprezentat de clasa
MouseEvent și include click de mouse, apăsare de buton, ridicare de buton, mișcare de mouse,
mouse intrând pe o suprafață, mouse ieșind de pe o suprafață etc.
- Key Event -> generata la o apăsare de tastă pe un nod JavaFX. Clasa reprezentativă este
KeyEvent. Include apăsare de tastă, eliberare tastă, tipărire tastă.
- Drag Event -> este un eveniment de input ce apare când mouse-ul este tras (cu butonul
semnificativ apăsat). Clasa reprezentativă este DragEvent iar exemple sunt: tragerea peste o
suprafața (drag entered), anularea tragerii (drag dropped), tragerea peste o anumită suprafață
(drag entered target), tragerea în afara unei anumite suprafețe (drag exited target) etc.
- Window Event -> legate de afișarea (show)/ascunderea unei ferestre. Clasa folosită este
WindowEvent și acțiuni exemplu sunt: ascunderea unei ferestre, afișarea unei ferestre,
fereastră ascunsă, fereastră afișată etc.
JavaFX – Evenimente.
Evenimentele sunt organizate ierarhic. Orice eveniment are un nume și un super-tip. De
exemplu, numele unui eveniment pentru o apăsare de tastă este KEY_PRESSED, care are
ca super-tip pe KeyEvent.ANY. Super-tipul evenimentului din vârful ierarhiei este null.
JavaFX – Evenimente.
Tratarea evenimentelor este mecanismul care controlează evenimentele și decide ce
urmează să se întâmple dacă un anumit eveniment are loc. Codul pentru acest lucru se
numește „event handler”. JavaFX pune la dispoziție conceptele de handler și filter.
Orice evenimente JavaFX are următoarele proprietăți:
- Target -> nodul pe care s-a întâmplat evenimentul. Acesta poate fi o fereastră, scenă,
alt nod.
- Source -> sursa de unde este generat evenimentul (mouse sau tastatură)
- Type -> tipul evenimentului care s-a produs. De exemplu: mouse pressed, mouse
released etc.
JavaFX – Evenimente.
Să considerăm, de exemplu, o aplicație JavaFX cu un cerc roșu și două butoane („stop” și
„play”) introduse ca un grup în interfața grafică. Dacă apăsam pe „play” vom avea:
- Source -> mouse-ul
- Target -> butonul „play”
- Type -> mouse click
JavaFX – Evenimente.
Tratarea unui eveniment JavaFX are un set de pași prestabiliți:
1. Construirea rutei -> la generarea unui eveniment ruta inițială este determinată prin
construirea unui lanț de lansare a evenimentului (event dispatch chain). Acesta reprezintă de
fapt calea din stage până la nodul sursă.
2. Capturarea evenimentului (event capturing) -> după pasul 1, nodul rădăcină al aplicației
lansează evenimentul, care trece prin toate nodurile lanțului (de sus în jos). Dacă oricare
dintre aceste noduri are un filtru înregistrat pentru respectivul eveniment, acesta va fi
executat. Dacă nici un nod din lanț nu are un filtru pentru respectivul eveniment, acesta este
pasat către nodul target iar acesta procesează evenimentul.
JavaFX – Evenimente.
3. Întoarcerea la nodul sursă (event bubbling phase) -> evenimentul este din nou trimis
de la nodul țintă către stage (de jos în sus). Dacă oricare dintre nodurile din lanț are
un handler înregistrat pentru respectivul eveniment acesta va fi executat. Dacă nu,
evenimentul ajunge la nodul rădăcină și procesul este definitivat.
4. Tratare și filtrare eveniment (handler și filter)-> handler și filter sunt elementele care
conțin logică aplicației pentru procesarea unui eveniment. Un nod poate fi înregistrat
la mai multe handler-e/filtre. În cazul nodurile părinte-copil putem utiliza
filtre/handler-e comune la nivelul părintelui, care se vor procesa ca implicite pentru
toate nodurile lor copil.
Pe parcursul unui eveniment, procesarea acestuia este un filtru ce se execută iar în pasul
3 se execută un handler. Toate filtrele/handler-ele implementează interfața EventHandler
din pachetul javafx.event.
JavaFX – Evenimente.
Un eveniment poate fi „consumat” (încheiat) de către un filtru sau un handler în orice
moment, utilizând metoda consume(). Această metodă semnalează că procesarea
evenimentului s-a încheiat și nu mai continuă traversarea rutei evenimentului (event
dispatch chain). ÎNSĂ, dacă nodul care consumă evenimentul are mai mult de un filtru sau
handler înregistrat pentru respectivul eveniment, aceste filtre/handler-e se execută și ele.
Logica aplicației introdusă la nivel de filter se execută înainte de cea de la nivel handler.
JavaFX – Evenimente. Metode rapide.
În JavaFX putem utiliza o procedură mai simplă de a înregistra handler-e de evenimente,
cu ajutorul metodelor rapide („comode” - convenience methods).
Aceste metode sunt în general definite în clasa Node și sunt disponibile tuturor
subclaselor acesteia. În continuare avem un tabel sintetic cu acțiunile, tipul de eveniment
și clasa – pentru clasele care pot folosi metode rapide.
Acțiune Tip eveniment Clasa
Apăsare tastă KeyEvent Node, Scene
Mișcare mouse sau apăsare buton mouse MouseEvent Node, Scene
Proces complet apăsare buton-tragere-eliberare buton MouseDragEvent Node, Scene
de mouse
Input de la o metodă alternativă de introducere InputMethodEvent Node, Scene
caractere (o limbă străină) este generat, schimbat,
anulat, definitivat
Tragere/eliberare dependente de platformă DragEvent Node, Scene
JavaFX – Evenimente. Metode rapide.
…continuare:
Acțiune Tip eveniment Clasa
Derulare (scroll) ScrollEvent Node, Scene
Rotație a unui obiect RotateEvent Node, Scene
Gest swipe pe un obiect SwipeEvent Node, Scene
Atingere obiect TouchEvent Node, Scene
Zoom aplicat unui obiect ZoomEvent Node, Scene
Cererea meniului contextual ContextMenuEvent Node, Scene
Apăsarea unui buton, afișarea/ascundere unui combo- ActionEvent ButtonBase,
box, selectarea unui element de meniu ComboBoxBase,
ContextMenu,
MenuItem,
TextField
Editarea unui element dintr-o listă, tabel, tree ListView.EditEvent ListView
TableColumn.CellEdit TabelColumn
Event
TreeView.EditEvent TreeView
JavaFX – Evenimente. Metode rapide.
…continuare:
Acțiune Tip eveniment Clasa
Eroare întâlnită de MediaPlayer MediaErrorEvent MediaView
Ascundere/afișare meniu Event Meniu
Ascundere fereastră popup Event PopupWindow
Tab selectat sau închis Event Tab
Fereastră închisă, afișată sau ascunsă WindowEvent Window
cerc.setFill(Color.YELLOW);
};
cerc.addEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler1);
JavaFX – Evenimente. Filtre.
Pentru îndepărtarea unui filtru se folosește metoda removeEventFiltre().
cerc.removeEventFilter(MouseEvent.MOUSE_CLICKED, eventHandler1);
JavaFX – Evenimente. Handler.
Adăugarea unui handler de eveniment la un nod se face prin înregistrarea acestuia cu ajutorul
metodei addEventHandler(), din clasa Node.
cerc.setFill(Color.PINK);
};
cerc.addEventHandler(javafx.scene.input.MouseEvent.MOUSE_CLICKED, eventHandler2);
JavaFX – Evenimente. Handler.
Pentru îndepărtarea unui handler se folosește metoda removeEventHandler().
cerc.removeEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler2);