Documente Academic
Documente Profesional
Documente Cultură
Curs – 8
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 .
- desenarea
- comandarea sistemului de ferestre pentru a afisa desenul realizat anterior
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 .
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 metode
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 buclucasul ciclu while de mai sus ; primul lucru facut in ciclu este
apelarea repaint() pentru redesenarea ferestrei . Tot aici vom intalni si o noua metoda :
sleep() . Aceasta metoda a clasei Thread determina o pauza in executie . Daca nu s-ar
folosi aceasta metoda appletul ar rula la viteza maxima , lucru care poate sa nu fie
conform cu dorinta programatorului . Instructiunile try si catch vor apare aici pentru
tratarea erorilor si pentru moment le putem ignora .
Metoda paint() a appletului creaza o noua instanta a clasei Date - pentru folosirea
acestei clase trebuie sa o importam , ea fiind inclusa in java.util . De asemenea apare
si metoda toString() a clasei Date , necesara pentru afisarea ca sir a datei si orei . La
fiecare apelare a metodei paint() vom avea astfel un nou obiect Date care va tine ora si
data curente .
Sa vedem in continuare codul sursa al appletului descris anterior :
import java.awt.*;
import java.util.*;
Acest efect - cu denumirea in limba engleza , traducerea fiind palpaire - este cauzat de
modul de reimprospatare a fiecarui caddru de animatie . Dupa cum am mai spus :
apelul metodei repaint() duce automat la un apel al metodei repaint() .De fapt mai
exista inca o metoda intermadiara 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 :
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 .
import java.awt.*;
Pentru a intelege cat mai bine appletul sa incercam un comentariu aproape linie cu
linie al codului 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 destulde 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 acest moment , ori de cate ori va trebui sa desenam pe ecran - cu metoda paint() -
vom desena in contextul grafic invizibil ; ca exemplu , pentru a desena o imagine
numita img la pozitia 100,100 folosim linia de cod :
invizibil.drawImage(img,100,100,this);
In ceea ce priveste cuvantul cheie this folosit aici nu va faceti probleme pentru ceea ce
reprezinta - va fi prezentat mai detaliat in paginile urmatoare .
Ultima etapa , dupa ce s-a terminat de desenat totul in contextul invizibil ,
instructiunea urmatoare copiaza zona tampon invizibila pe ecran :
ecran.drawImage(imagineInvizibila,0,0,this);
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);
}
- 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;
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 )
:
Image imagine=getImage(getDocumentBase(),"imagine1.gif");
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 :
Scalarea imaginii are efect doar pentru afisarea in applet , obiectul propriu-zis nefiind
alterat de aceste apeluri de metoda .
Ultiimul 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 ) .
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
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 :
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");
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 .
import java.awt.*;
import java.applet.*;
AudioClip sunetFundal;
AudioClip bip;
Thread executabil;