Objektno orijentisano programiranje Java GUI poetak 1 GUIji
Objektno orijentisano programiranje Java, GUI početak 1
GUI-ji u Javi • GUI – grafički korisnički interfejs • Postoji ogromna funkcionalnost u Javinim bibliotekama klasa za podršku GUI. • Sve to nemoguće je obuhvatiti jednom knjigom • Samo klasa JFrame sadrži preko 200 metoda uključujući one nasleđene od superklasa • Bićemo jako selektivni u pogledu klasa koje ćemo upoznati i njihovih metoda • Pokrićemo samo ono osnovno što nam je potrebno da kreiramo svoje aplikacije i aplete • Osnovni elementi koji nam trebaju za kreiranje GUI-ja nalaze se u 2 paketa: java. awt i javax. swing. 2
GUI-ji u Javi • Paket java. awt je u Javi 1. 1 bio primarno skladište klasa za kreiranje GUI-ja ( Abstract Windowing Toolkit ), ali mnoge od klasa koje ovaj paket definiše zamenjene su u Javi 2 klasama iz javax. swing. Mnoge klase, ne sve. • Većina klasa paketa javax. swing koje definišu GUI elemente, tzv. Swing komponente, obezbeđuju dosta unapređene alternative za komponente definisane klasama iz java. awt paketa. • Npr. JButton klasa iz javax. swing u odnosu na Button klasu iz java. awt • Međutim, Swing klase su izvedene i samim tim zavise od osnovnih klasa definisanih u java. awt paketu i to ne možemo ignorisati. 3
GUI-ji u Javi • Swing klase su deo opštijeg skupa, tzv. Java Foundation Classes ( JFC ) klasa za programiranje GUI-ja. JFC pored Swing klasa sadrži takođe i klase za 2 D crtanje iz paketa java. awt. geom i klase koje podržavaju drag-and-drop iz paketa java. awt. dnd. JFC takođe uključuje application program interface (API) definisan u paketu javax. accessibility • Swing klase su fleksibilnije od odgovarajućih klasa iz paketa java. awt, pošto su u potpunosti implementirane u Javi. ( java. awt komponente u velikoj meri zavise od native-koda). Pošto su Swing komponente "čista" Java, nisu ograničene karakteristikama platforme na kojoj se izvršavaju. • Pored dodatne funkcionalnosti i fleksibilnosti Swing komponenata, one imaju i tzv. pluggable look-and-feel svojstvo koje omogućava promenu izgleda komponente. Možemo programski izabrati za komponentu neki od standardnih ili kreirati sopstveni look-and-feel ako želimo. (pluggable look-and-feel je olakšan dizajniranjem klasa na poseban način, tzv. Model-View-Controller arhitekturom – MVC) • MVC nije od posebnog značaja za primenu Swing klasa, ali jeste ako hoćemo da modifikujemo pluggable look-and-feel komponente. 4
Kreiranje prozora • Osnovni prozor u Javi predstavljen je objektom klase Window, definisane u paketu java. awt • Međutim, objekti ove klase jedva da se ikada koriste direktno jer ova klasa ne obezbeđuje neke osnovne stvari potrebne za prozor aplikacije poput title bar-a i okvira. • Klasa JFrame paketa javax. swing je mnogo korisnija za kreiranje prozora jer nudi obilje mogućnosti. • Njene superklase: java. lang Object Component definiše komponentu, entitet koji se može prikazati Container definiše komponentu koja može sadržati druge kompon. java. awt Window definiše osnovni prozor bez titile bar-a i okvira Frame definiše prozor sa title bar-om i okvirom javax. swing JFrame definiše frame – to je prozor sa proširenim mogućnostima 5
Kreiranje prozora • Klasa Component definiše osnovna svojstva i metode za sve komponente. Videćemo kasnije da je to bazna klasa za sve Swing komponente • Klasa Container dodaje mogućnost Component objektu da sadrži druge komponente, što je česta potreba – Pošto klasa JFrame ima Container za superklasu, JFrame objekat može sadržati druge komponente. – menu bar treba da sadrži menije npr. a toolbar dugmad itd. Iz tog razloga klasa Container je takođe bazna za sve klase koje definišu Swing komponente. • Klasa Window dodaje klasi Container metode specifične za prozor, poput rukovanja događajima koji nastaju interakcijom korisnika sa prozorom • Klasa JFrame dodaje klasi Frame mnogo sofisticiranije mogućnosti za crtanje i prikaz drugih komponenti 6
Kreiranje prozora • Možemo prikazati prozor aplikacije kreiranjem objekta tipa JFrame, pozivom metoda objekta za postavljanje veličine prozora, a zatim pozivom metoda za prikaz prozora import javax. swing. JFrame; public class Test. Window { // objekat prozor static JFrame prozor = new JFrame("Naslov prozora"); public static void main(String[] args){ int sirina. Prozora=400; // sirina prozora u pikselima int visina. Prozora=150; // visina prozora u pikselima prozor. set. Bounds(50, 100, sirina. Prozora, visina. Prozora); // postavljanje velicine i pozicije prozor. set. Default. Close. Operation(JFrame. EXIT_ON_CLOSE); prozor. set. Visible(true); // prikaz prozora } 7 }
Kreiranje prozora, Test. Window • Ovaj prozor je potpuno operativan. Moguće je promeniti veličinu prozora, minimizovati ga, zatvoriti aplikaciju klikom na X. • Program će se završiti uredno ako smo korektno uneli kod. Ako dođe do grešaka, to se neće desiti. Ako se iz bilo kog razloga aplikacija ne završi regularno, Ctrl+Alt+Delete, pa se iz Task Manager-a završi aplikacija • U prethodnom programu, objekat tipa JFrame se kreira i smešta kao inicijalna vrednost statičkog atributa klase Test. Window, pa će on biti automatski kreiran kada se učita klasa Test. Window. Argument konstruktora definiše naslov koji će biti prikazan u prozoru aplikacije. • main() metod poziva 3 metoda za objekat prozor. • Metod set. Bounds() definiše veličinu i poziciju prozora, prva 2 argumenta odgovaraju x i y koordinatama gornjeg levog ugla prozora aplikacije relativno u odnosu na gornji levi ugao ekrana, dok drugi par argumenata određuje širinu i visinu prozora u pikselima 8
Kreiranje prozora, Test. Window • Koordinatni sistem ekrana ima koordinatni početak (0, 0) u gornjem levom uglu ekrana, pozitivna x-osa ide sleva na desno, a pozitivna y -osa odozgo nadole • (50, 100) gornji levi ugao prozora • širina prozora 400 • visina prozora 150 donji desni ugao na poziciji (450, 250) 9
Kreiranje prozora, Test. Window • Stvarna fizička širina i visina prozora zavisiće od veličine ekrana i rezolucije. Za datu veličinu ekrana, što je veća rezolucija, to će prozor biti manji i bliži gornjem levom uglu ekrana. • Metod set. Default. Close. Operation() za objekat tipa JFrame određuje šta se dešava kada zatvorimo prozor, bilo klikom na X bilo izborom Close iz menija koji se prikaže kada kliknemo na Java-ikonicu u gornjem levom uglu prozora • Postoje 4 argumenta koje možemo da koristimo za ovaj metod • U primeru je korišćena konstanta EXIT_ON_CLOSE definisana u klasi JFrame. Njen efekat je: zatvaranje prozora, oslobađanje resursa prozora i komponenti koje on sadrži i završavanje aplikacije • Ostale 3 vrednosti koje možemo koristiti kao argument set. Default. Close. Operation() metoda, definisane su u Window. Constants interfejsu i to su: DISPOSE_ON_CLOSE okvir i komponente koje on sadrži se uništavaju, ali aplikacija se ne završava DO_NOTHING_ON_CLOSE operacija zatvaranja prozora neće imati nikakvog efekta HIDE_ON_CLOSE prozor se samo skriva pozivom metoda set. Visible() sa argumentom false. Ovo je default 10 uvek akcija ako ne pozovemo set. Default. Close. Operation() metod. Kada je prozor skriven, se može kasnije ponovo prikazati pozivom metoda set. Visible() sa argumentom true.
Kreiranje prozora, Test. Window • Možda želimo da preduzmemo još nešto osim ovih opcija kada korisnik izabere zatvaranje prozora. Npr. da pitamo korisnika da li želi da sačuva podatke koje je unosio pre završetka programa. To uključuje obradu događaja pridruženog Close stavci menija ili Close dugmetu. O tome kasnije. • Metod set. Visible() sa argumentom true prikazuje prozor aplikacije preko svih prozora koji su trenutno vidljivi na ekranu • Metodi set. Bounds() i set. Visible() su članovi klase JFrame nasleđeni od klase Component, pa su dostupni za svaku komponentu. Međutim, kao što ćemo videti, obično za ostale komponente ne postavljamo veličinu i poziciju. • Metod set. Default. Close. Operation() definisan je u klasi JFrame, pa je primenljiv samo za JFrame prozor objekte. 11
Komponente i kontejneri • Komponenta predstavlja grafički entitet koji može biti prikazan na ekranu • Komponenta je svaki objekat klase koja je potklasa klase Component. • Kao što smo videli, JFrame prozor je komponenta, ali postoje i mnoge druge • Na narednom slajdu su prikazane neke od potklasa klase Component, one koje su nama bitne. 12
Komponente i kontejneri 13
Komponente i kontejneri • Tipična upotreba ključnih klasa ove hijerarhije: JFrame koristi se kao osnovni prozor aplikacije. Objekat ove klase ima title bar i mogućnost dodavanja menija i drugih komponenata. Najčešće ćemo praviti potklasu ove klase kako bismo kreirali prozor specifičan za našu aplikaciju JWindow prozor bez title bar-a i ikona za upravljanje prozorima. Tipično se koristi kao pomoćni prozor aplikacije kada ima više displeja u sistemu JDialog za kreiranje dijalog prozora koji služi za unos podataka u program na različite načine. Obično kreiramo dijalog kao odgovor na izbor neke stavke menija ili klika na dugme JApplet bazna klasa za Java 2 aplet – program koji je napravljen da radi ugrađen u web stranu. Moguće je crtati u JApplet, dodavati menije i druge komponente JComponent potklase ove klase definišu niz standardnih komponenti poput menija, dugmadi, checkbox-ova itd. Koristimo ih za kreiranje GUI-ja aplikacije ili apleta 14
Komponente i kontejneri • Sve klase izvedene iz Container mogu sadržati druge objekte proizvoljnih klasa izvedenih iz Component. Pošto je klasa Container potklasa klase Component, svaki objekat kontejner je i Component takođe, pa kontejner može sadržati i druge kontejnere • Izuzetak su klasa Window i njene potklase, objekti tipa Window ( ili njene potklase ) ne mogu biti sadržane u drugom kontejneru. Ako to pokušamo biće izbačen izuzetak. • Klasa JComponent je bazna za sve Swing komponente korišćene u prozoru kao deo GUI-ja, i pošto je ova klasa izvedena iz Container, sve Swing komponente su takođe kontejneri. • Klasa JApplet, koja je bazna za sve Swing aplete, izvedena je iz Component preko klase Container, pa će time aplet naslediti metode iz obe te klase. On takođe nasleđuje metode stare klase Applet koje dalje unapređuje. • Klase JApplet, JFrame, JDialog i JComponent se sve nalaze u paketu javax. swing • Applet je u java. applet, a sve ostale su u java. awt • Uvek ćemo koristiti klasu JApplet za definisanje apleta, pošto je ona 15 značajno bolja od Applet
Window i Frame komponente • • • Osnovna razlika između JFrame objekta i Window objekta je ta što JFrame objekat predstavlja glavni prozor aplikacije, dok nam je za kreiranje Window objekta uvek neophodno da prethodno imamo JFrame objekat Pošto je klasa JDialog direktno izvedena iz klase Window, možemo kreirati JDialog objekat u aplikaciji jedino u kontekstu JFrame objekta. Osim podrazumevanog konstruktora, konstruktori klase JDialog generalno zahtevaju JFrame objekat kao argument, i taj JFrame objekat je roditelj JDialog objekta. JFrame objekat ima okvir, promenljive je veličine, može imati ugrađeni menu bar. Pošto je JFrame objekat glavni prozor aplikacije, njegova veličina i pozicija definisane su relativno u odnosu na ekran. JDialog objekat sa JFrame roditeljskim objektom biće smešten relativno u odnosu na roditelja. Dakle, JApplet, JFrame, JDialog su sve kontejneri pošto sve imaju klasu Container za baznu, pa mogu sadržati komponente. One su takođe same po sebi komponente pošto su izvedene iz klase Component. Međutim, nije sve baš tako jednostavno. Komponente za svoj GUI ne dodajemo direktno JFrame ili JApplet objektu našeg programa. 16
Prozorski okviri (Window panes) • Kada želimo da dodamo GUI komponente ili crtamo u prozoru prikazanom JFrame objektom, mi dodajemo komponente ili crtamo u prozorski okvir rukovođen JFrame objektom. Isto važi i za aplet. • Uopšteno govoreći, prozorski okviri su kontejnerski objekti koji predstavljaju površ prozora i ima ih više vrsta. • Najveći deo vremena koristimo content pane. • odnos content. Pane objekta, drugih prozorskih okvira i prozora aplikacije prikazan je na narednom slajdu 17
Prozorski okviri (Window panes) 18
Prozorski okviri (Window panes) • • content. Pane – u njega obično dodajemo komponente osim menubar-a. Kada pozovemo metod get. Content. Pane() za JFrame objekat, dobijemo referencu na njega. Površ JFrame prozora ispod title bar-a odgovara JRoot. Pane objektu. On sadrži drugi okvir, objekat layered. Pane sa slike, koji je tipa JLayered. Pane. Ovaj okvir odgovara celoj površi koju zauzima JRoot. Pane objekat prozora i obrađuje menu bar ako on postoji u prozoru. Površ u layered. Pane ispod menu bar-a odgovara content. Pane objektu i tu tipično dodajemo GUI komponente. Takođe, prikaz teksta i crtanje radimo u površi pokrivenoj content pane-om. layered. Pane objekat ima specijalna svojstva za napredne aplikacije koje dopuštaju rukovanje grupama komponenata u različitim lejerima koji preklapaju jedni druge unutar okvira. Sa ovom mogućnošću možemo kontrolisati kako će se komponente prikazivati relativno u odnosu na druge komponente, pošto se lejeri prikazuju određenim redosledom od pozadi ka napred. Komponente prednjeg lejera pojaviće se na ekranu ispred onih koje se nalaze u lejeru koji je negde pozadi. 19
Prozorski okviri (Window panes) • Takođe, postoji i 1 dodatni okvir koji nije prikazan na slici, i to je glass. Pane objekat, koji takođe odgovara čitavoj JRoot. Pane površi. Sadržaj glass. Pane objekta prikazuje se povrh svih ostalih okvira, pa se on koristi za prikaz komoponenti koje želimo da budu iznad svega ostalog prikazanog u prozoru – npr. za drop-down menije ili za prikaz grafike koja se relativno često ažurira – npr. animacije. • Kada deo onoga što se prikazuje treba da se animira, statička pozadina može biti nezavisno prikazana pomoću content. Pane. Pošto ona ne mora da se reprocesira svaki put kada animirani objekti treba ponovo da se iscrtaju, ceo proces biće mnogo efikasniji • Klasa JFrame definiše metode pomoću kojih možemo dobiti referencu na proizvoljni okvir: get. Root. Pane() povratni tip metoda je JRoot. Pane get. Layered. Pane() JLayeded. Pane get. Content. Pane() Container 20 get. Glass. Pane() Component
Prozorski okviri (Window panes) • Sve ovde opisane klase koje predstavljaju okvire same po sebi su Swing komponente, definisane u paketu javax. swing • JApplet objekat ima isti raspored okvira kao i JFrame objekat, pa se dodavanje komponenti i crtanje u apletu vrši na potpuno isti način. • Aplet definisan kao JApplet objekat takođe može imati menu bar upravo kao i prozor aplikacije. • Svi okviri, kao i menu bar, su komponente. 21
Osnove komponenata • Postoji nekoliko osnovnih koncepata zajedničkih za sve komponente • Iako sada sledi puko nabrajanje klasa i metoda, većina tih mogućnosti biće praktično upotrebljena kasnije • Da bismo razumeli osnovne stvari koje možemo raditi sa Swing komponentama, istražićemo funkcionalnost koju one nasleđuju od Component i Container. • Kada je neka komponenta sadržana u nekoj drugoj, ta druga se zove roditelj. Referencu na roditeljski objekat za svaku datu komponentu možemo dobiti pozivom metoda get. Parent(). Ovaj metod se nasleđuje od klase Component, i vraća tip Container, pošto jedino potklasa od Container može sadržati druge komponente. Ako nema roditelja, npr. u slučaju JFrame komponente, metod vraća null. 22
Atributi klase Component • Atributi klase Component čuvaju sledeće informacije o objektu: position (x, y) koordinate; gde je objekat smešten u odnosu na njegov kontejner, u koordinatnom sistemu kontejnerskog objekta name ime komponente, tipa String size vrednosti za širinu i visinu objekta foreground color i background color boje za objekat font koji koristi objekat kada prikazuje tekst cursor definiše izgled kursora kada je iznad objekta enable da li je objekat omogućen ili nije – kada jeste, njegovo enabled stanje je true i objekat izgleda normalno, a u suprotnom je sive boje. onemogućen objekat takođe može generisati događaje visible da li je objekat vidljiv na ekranu ili nije; ako objekat nije označen kao vidljiv, ne iscrtava se na ekranu valid da li je objekat validan ili nije – ako nije layout entiteta koji sačinjavaju objekat nije određen. To je slučaj pre nego što 23 objekat postane visible
Atributi klase Component • Karakteristike Component objekta možemo menjati samo pozivanjem njegovih metoda ili utičući na njih indirektno na neki način pošto su sve deklarisane kao private. • Npr. ime Component objekta my. Window možemo promeniti sa: my. Window. set. Name("Novo ime"); • Metod get. Name() vraća ime objekta, kao String: String ime=my. Window. get. Name(); • Metodi is. Visible(), is. Enabled(), is. Valid() vraćaju true ako je objekat visible, enabled i valid, redom. • Možemo postaviti da objekat bude visible ili enabled prosleđivanjem vrednosti true kao argumenta metodima set. Visible() i set. Enabled(), redom. 24
Atributi klase Component • Uobičajena zabluda sa Swing komponentama je ta da će poziv set. Enabled(false) sprečiti događaje poput klika mišem na komponentu. To nije slučaj. Sve što taj poziv radi jeste da postavi interni enabled status na false uzrokujući da komponenta posivi. Da bismo sprečili da događaji onemogućene komponente imaju efekta, moramo pozvati is. Enabled() za komponentu u kodu za obradu događaja da utvrdimo da li je komponenta omogućena ili ne. A onda možemo da odlučimo da ne radimo ništa ako metod is. Enabled() vrati false. 25
Veličina i pozicija komponente • Pozicija je definisana x i y koordinatama tipa int ili objektom tipa java. awt. Point • Objekat Point ima 2 public atributa, x i y. • Veličina je definisana int vrednostima width i height ili objektom tipa java. awt. Dimension • Klasa Dimension ima 2 public atributa, width i height. • Veličina i pozicija komponente se često zadaju zajedno objektom tipa java. awt. Rectangle • Rectangle objekat ima public atribute x i y, koji definišu gornji levi ugao pravougaonika, i atribute width i height, koji definišu njegovu veličinu. Svi ovi atributi su tipa int. • Komponente imaju tzv. "prioritetnu" (preferred) veličinu definisanu java. awt. Dimension objektom koji enkapsulira vrednosti za širinu i visinu. Ta veličina varira u zavisnosti od objekta. Npr. ta veličina za JButton objekat koji definiše dugme je veličina koja se prilagođava labeli dugmeta 26
Veličina i pozicija komponente • Veličina komponente se određuje automatski kada ona ima roditeljsku komponentu. O tome kasnije. • Komponenta takođe ima minimalnu i maksimalnu veličinu • Veličina komponente će biti između minimalne i maksimalne, a ako je prostor raspoloživ za tu komponentu manji od njene minimalne veličine, komponenta neće biti prikazana • Možemo postaviti "prioritetnu", minimalnu i maksimalnu veličinu komponente • Metodi klase Component za pristup veličini i poziciji su: Rectangle get. Bounds() vraća veličinu i poziciju objekta kao objekat tipa Rectangle get. Bounds(Rectangle rect) smešta poziciju i veličinu u Rectangle objekat koji prosledimo kao argument i vraća referencu na rect. Ova verzija metoda omogućuje ponovnu upotrebu postojećeg Rectangle objekta. Ako je rect null, metod će kreirati novi Rectangle objekat. Dimension get. Size() vraća tekuću veličinu Component objekta kao Dimension objekat Dimension get. Size(Dimension dim) Point get. Location() vraća poziciju Component objekta kao objekat tipa Point 27 Point get. Location(Point p)
Veličina i pozicija komponente • Pozicija i/ili veličina komponente mogu se promeniti korišćenjem sledećih metoda: void set. Bounds(int x, int y, int width, int height) void set. Bounds(Rectangle rect) void set. Size(Dimension d) set. Location(int x, int y) set. Location(Point p) • Takođe, mogu se postaviti parametri za utvrđivanje opsega veličine void set. Minimum. Size(Dimension d) ako je argument null, veličina komponente biće podrazumevana minimalna veličina void set. Maximum. Size(Dimension d) void set. Preferred. Size(Dimension d) 28
Veličina i pozicija komponente • Još jedan bitan metod klase Component je get. Toolkit() • On vraća objekat tipa Toolkit koji sadrži informacije o okruženju u kom se aplikacija izvršava, uključujući i veličinu ekrana u pikselima. • Možemo koristiti ovaj metod kao pomoć pri postavljanju veličine i pozicije prozora na ekranu • Možemo modifikovati prethodni primer kako bismo to demonstrirali • Test. Window 2 • Koristimo Toolkit objekat da prikažemo prozor na sredini ekrana, sa širinom i visinom jednakim polovini širine i visine ekrana import java. awt. Toolkit; import java. awt. Dimension; . . . Toolkit the. Kit = prozor. get. Toolkit(); 29 Dimension velicina. Ekrana = the. Kit. get. Screen. Size();
Dimenzioniranje prozora pomoću Toolkit, Test. Window 2 • Toolkit objekat, the. Kit, dobijamo pozivom metoda get. Toolkit() za JFrame objekat prozor. Ovaj objekat predstavlja okruženje na našem računaru i enkapsulira svojstva i mogućnosti tog okruženja koja se tiču Jave, uključujući i rezoluciju i veličinu ekrana • Toolkit objekat nije moguće kreirati direktno pošto je Toolkit apstraktna klasa. Postoji samo 1 Toolkit objekat u aplikaciji, onaj na koji dobijemo referencu pozivom metoda get. Toolkit() za komponentu • Metod get. Screen. Size() je član Toolkit objekta i vraća objekat tipa Dimension koji sadrži atribute width i height sa vrednostima veličina širine i visine ekrana izraženim u broju piksela. Koristimo te vrednosti da bismo postavili koordinate za poziciju prozora i širinu i visinu prozora pomoću metoda set. Bounds(). 30
Centriranje prozora, Test. Window 3 • Ovo nije jedini način centriranja prozora. java. awt. Graphics. Environment objekat sadrži informacije o grafičkim uređajima u sistemu. • Referenca na Graphics. Environment objekat može se dobiti pozivom statičkog metoda get. Local. Graphics. Environment() klase Graphics. Environment : Graphics. Environment local. GE = Graphics. Environment. get. Local. Graphics. Environment(); • Onda se može pozvati metod get. Center. Point() da bi se dobio Point objekat sa koordinatama centra ekrana: Point centar = local. GE. get. Center. Point(); 31
Centriranje prozora, Test. Window 3 import java. awt. Graphics. Environment; . . . Point center = Graphics. Environment. get. Local. Graphics. Environment(). get. Center. Point(); int sirina. Prozora = 400; int visina. Prozora = 150; prozor. set. Bounds(center. x - sirina. Prozora/2, center. y - visina. Prozora/2, sirina. Prozora, visina. Prozora); . . . 32
Tačke i pravougaonici • • mala digresija: klase Point i Rectangle obe klase nalaze se u paketu java. awt Mnogi metodi ovih klasa su vrlo korisni za crtanje u prozoru Entiteti prikazani u prozoru tipično imaju pridružene Rectangle objekte koji definišu površi unutar prozora koje ti entiteti zauzimaju • Point objekti se koriste u definiciji drugih geometrijskih entiteta poput linija i krugova i za određivanje njihove pozicije u prozoru • Ni Point ni Rectangle objekti nemaju ugrađenu reprezentaciju na ekranu. Oni nisu komponente, oni su apstraktni geometrijski entiteti • Ako želimo da prikažemo pravougaonik, moramo da ga nacrtamo 33
Point objekti • 2 public atributa tipa int : x i y • Points. java • promena pozicije Point objekta: metod move() ili metod set. Location() ( postavljanje vrednosti atributa x i y ) • get. Location() metod vraća kopiju tekućeg Point objekta • translate() metod – za translaciju Point objekta • equals() metodom se porede 2 Point objekta. Porede se x i y koordinate objekata i metod vraća true ako su odgovarajući parovi koordinata jednaki. • Ovo nije jedina klasa koja predstavlja tačke 34
Rectangle objekti • 4 public atributa, tipa int • pozicija Rectangle objekta određena je atributima x i y, a njegova veličina atributima width i height • Pošto su svi atributi public, možemo im direktno pristupati i direktno ih menjati, ali će kod bti malo čitljiviji ako se koriste metodi koji su na raspolaganju • 7 konstruktora: Rectangle() // u tački (0, 0), sa dimenzijama 0, 0 Rectangle(int x, int y, int width, int height) Rectangle(int width, int height) // x = y = 0 Rectangle(Point p, Dimension d) Rectangle(Point p) // width = height = 0 Rectangle(Dimension d) // x = y = 0 35 Rectangle(Rectangle r) // iste dimenzije i pozicija kao r
Rectangle objekti • Pristup i promena pozicije Rectangle objekta – korišćenjem get. Location() metoda, koji vraća Point objekat i set. Location() koji ima 2 verzije: 1 zahteva x i y koordinate nove pozicije kao argumente, a druga Point objekat • Na Rectangle objekat može se primeniti metod translate() na isti način kao kod Point objekta. • Za pristup i promenu veličine Rectangle objekta koriste se metod get. Size() koji vraća Dimension objekat i set. Size() koji kao argument zahteva ili Dimension objekat koji određuje novu veličinu ili 2 argumenta tipa int koji odgovaraju novim vrednostima širine i visine. • Takođe, može se koristiti nekoliko metoda za kombinovanje Rectangle objekata i za proširenje Rectangle objekta tako da obuhvati datu tačku • Na narednom slajdu, pravouganoik koji predstavlja rezultat operacije prikazan je isprekidanom linijom 36
Rectangle objekti 37
Rectangle objekti Rectangle intersection(Rectangle r) vraća Rectangle objekat koji je presek tekućeg objekta i argumenta. Ako se ta 2 pravougaonika ne seku, vraća Rectangle objekat na poziciji (0, 0) i width = height = 0 Rectangle union(Rectangle r) vraća najmanji Rectangle objekat koji sadrži tekući i pravougaonik r void add(Rectangle r) proširuje tekući Rectangle objekat tako da obuhvati i argument r void add(Point p) proširuje tekući Rectangle objekat tako da obuhvati i tačku p. Rezultat je najmanji pravougaonik koji sadrži originalni pravougaonik i tačku void add(int x, int y) void grow(int h, int v) da obuhvati tačku (x, y) povećava tekući Rectangle objekat pomeranjem granica od centra za h po horizontali i za v po vertikali 38
Rectangle objekti • Sledećim metodima mogu se testirati i porediti Rectangle objekti na različite načine: boolean is. Empty() vraća true ako je width = height = 0, false inače boolean equals(Object rect) true ako su tekući i pragougaonik argument jednaki, false inače, a jednaki su ako su na istoj poziciji i imaju iste širine i visine. Ako argument nije Rectangle objekat, vraća se false. boolean intersects(Rectangle rect) boolean contains(Point p) vraća true ako se tekući i pravougaonik argument seku, false inače vraća true ako tekući Rectangle objekat obuhvata tačku p, false inače boolean contains(int x, int y) -||- tačku (x, y) • Svi ovi metodi biće korisni kada rukujemo sadržajem Java prozora • Postoje i druge klase koje definišu pravougaonike 39
Vizuelne karakteristike komponenti • 2 stvari određuju vizuelni izgled komponente: – reprezentacija komponente kreirana Java kodom u klasi komponente koji se izvršava kada se prikaže komponenta i – sve ono što se crta na komponenti • Component objekat se može iscrtati implementiranjem njegovog paint() metoda. Taj metod se poziva automatski kada treba nacrtati komponentu • Naša implementacija paint() metoda mora uključiti kod za generisanje svega onoga što želimo da iscrtamo unutar Component objekta. Sama komponenta – JButton ili JFrame npr. – biće automatski iscrtana, a paint() metod treba da predefinišemo samo za ono dodatno što hoćemo da nacrtamo na njoj. 40
Vizuelne karakteristike komponenti • Neke aspekte izgleda osnovne komponente možemo menjati pozivajući sledeće metode za objekat: void set. Background(Color a. Color) postavlja boju pozadine na a. Color. Boja pozadine je boja koja se koristi za osnovnu komponentu Color get. Background() vraća tekuću boju pozadine void set. Foreground(Color b. Color) postavlja na b. Color boju svega što se pojavljuje na osnovnoj komponenti. Npr. labele na dugmetu Color get. Foreground() vraća tekuću foreground boju void set. Font(Font a. Font) postavlja font Font get. Font() vraća font void set. Cursor(Cursor a. Cursor) postavlja izgled kursora unutar površine zauzete Component objektom • Da bismo mogli da koristimo ove metode, potrebno je da znamo šta su Color objekti i kako da kreiramo Color i Font objekte 41
Definisanje boje • Boja ekrana predstavlja se objektom klase Color ( java. awt ) • Vrednost boje definiše se kao kombinacija 3 osnovne boje: crvene, zelene i plave (RGB) • Postoje i drugi načini zadavanja boja u Javi, ali mi ćemo se zadržati na ovom • Intenzitet svake od osnovnih boja može imati vrednost od 0 do 255 • (0, 0, 0) – crna • (255, 255) – bela Color my. Black = new Color(0, 0, 0); // crna boja Color my. White = new Color(255, 255); // bela boja Color my. Green = new Color(0, 200, 0); // nijansa zelene • 3 argumenta konstruktora odgovaraju intenzitetima crvene, zelene i plave boje, redom 42
Definisanje boje • Klasa Color definiše i public final static promenljive za standardne boje: WHITE (255, 0) RED (255, 0, 0) PINK (255, 175) LIGHT_GRAY (192, 192) ORANGE (255, 200, 0) MAGENTA (255, 0, 255) GRAY (128, 128) YELLOW (255, 0) CYAN (0, 255) DARK_GRAY (64, 64) GREEN (0, 255, 0) BLUE (0, 0, 255) BLACK (0, 0, 0) • Kada smo kreirali Color objekat, možemo posvetliti ili potamniti boju pozivom metoda brighter() i darker() koji uvećavaju ili umanjuju intenzitet komponenti boje za predefinisani faktor boja. brighter(); 43 boja. darker();
Definisanje boje • Intenziteti komponenti boje uvek ostaju između 0 i 255. Faktor koji se koristi za potamnjivanje komponente je 0. 7. Za posvetljivanje komponente, intenzitet se povećava korišćenjem faktora 1/0. 7 • Ovde je bitno da možemo dobiti samo boje koje podržavaju računar i okruženje operativnog sistema na kom se Java program izvršava. Ako je na raspolaganju ograničen broj boja, ovi metodi možda neće imati efekta • Možemo dobiti intenzitet svake od komponenti boje pomoću: get. Red(), get. Green() i get. Blue() metoda nad Color objektom. • Boja se takođe može dobiti i kao vrednost tipa int koja je kombinacija komponenata boje Color objekta korišćenjem get. RGB() metoda • Moguće je i kreirati Color objekat od 1 RGB vrednosti tipa int. 44
Definisanje boje • Metod equals() poredi 2 Color objekta i vraća true ako su odgovarajuće komponente boja jednake. • == ne treba koristiti za poređenje Color objekata, jer se time utvrđuje da li 2 reference na Color objekte referišu na isti objekat u memoriji • Može se koristiti get. RGB() metod za poređenje boja: if( boja. A. get. RGB() == boja. B. get. RGB() ) { // radimo nesto… } • ovo poredi 2 integer RGB vrednosti na jednakost, pa ovde == proizvodi korektan rezultat • klasa Color podržava i providnost boja čuvanjem vrednosti α iz opsega 0. 0 do 1. 0, gde je 0. 0 potpuno providno, a 1. 0 potpuno neprovidno 45
Sistemske boje • U paketu java. awt nalazi se potklasa System. Color klase Color. Ova klasa enkapsulira standardne boje koje host operativni sistem koristi za prikaz različitih komponenti • Klasa sadrži definicije 24 public final static promenljivih tipa System. Color koje određuju standardne sistemske boje koje sistem koristi za GUI komponente. Npr. za sistemske boje za prozor: window definiše boju pozadine za prozor window_text definiše boju teksta za prozor window_border definiše boju ivice prozora • Ako su nam potrebne i druge, npr. boje za menije, naslove, kontrole itd. možemo ih naći u dokumentaciji klase System. Color. • Ako želimo da poredimo System. Color vrednost sa Color objektom, moramo koristiti get. RGB() u poređenju: if( boja. A. get. RGB() == System. Color. window. get. RGB() ) { // … 46 }
Kreiranje kursora • Objekat java. awt. Cursor klase enkapsulira bitmap-reprezentaciju kursora miša • Ova klasa sadrži final static konstante koje određuju standardne tipove kursora. Njih koristimo za izbor ili kreiranje određenog kursora • Standardni tipovi kursora su: DEFAULT_CURSOR N_RESIZE_CURSOR NE_RESIZE_CURSOR CROSSHAIR_CURSOR S_RESIZE_CURSOR NW_RESIZE_CURSOR WAIT_CURSOR E_RESIZE_CURSOR SE_RESIZE_CURSOR TEXT_CURSOR W_RESIZE_CURSOR SW_RESIZE_CURSOR HAND_CURSOR MOVE_CURSOR • Resize kursori su oni koje vidimo kada menjamo veličinu prozora povlačenjem njegovih ivica. Ove konstante nisu kao Color konstante koje su Color objekti – ove konstante su tipa int, ne tipa Cursor, i namenjene su da se koriste kao argumenti konstruktora 47
Kreiranje kursora • Da bismo kreirali Cursor objekat koji predstavlja tekst-kursor: Cursor my. Cursor = new Cursor(Cursor. TEXT_CURSOR); • Alternativno, možemo dobiti kursor nekog od predefinisanih tipova korišćenjem statičkog metoda Cursor my. Cursor = Cursor. get. Predefined. Cursor(Cursor. TEXT_CURSOR); • Ovaj metod je posebno koristan kada ne želimo da pamtimo Cursor objekat, nego samo da ga prosledimo metodu poput set. Cursor() za Component objekat • Ako želimo da vidimo kako izgledaju standardni kursori, modifikujemo prethodni primer – promenimo background boju za content pane prozora aplikacije i probamo različite kursore : import java. awt. Color; import java. awt. Cursor; //. . . prozor. set. Cursor(Cursor. get. Predefined. Cursor(Cursor. TEXT_CURSOR)); prozor. get. Content. Pane(). set. Background(Color. PINK); 48
Fontovi • Objekat tipa Font predstavlja font. Klasa Font je zapravo prilično komplikovana, pa ćemo videti samo njen delić. • Ova klasa razlikuje karakter i glif ( glyph ), tj. oblik u kom će se slovo pojaviti kada se prikaže ili odštampa. Za karaktere koji odgovaraju mnogim jezicima karakter može uključiti više od jednog glifa za njegovo prikazivanje. • Da bismo kreirali Font objekat moramo proslediti ime fonta, stil i veličinu. Npr. Font my. Font = new Font( "Serif", Font. ITALIC, 12 ); • ovo definiše 12 -point Times Roman italic font • Preostale opcije koje se mogu koristiti za stil su PLAIN i BOLD • Ime koje je ovde upotrebljeno, "Serif", je logičko ime fonta. Druga logička imena mogla bi da budu "Dialog", "Dialog. Input", "Monospaced" ili "Sans. Serif". 49
Fontovi • Umesto logičkog imena fonta može se proslediti fizičko ime poput "Times New Roman" ili "Palatino". • Swing komponente rade i sa logičkim i sa fizičkim fontovima, dok AWT mogu da koriste samo logičke fontove. • Logička imena imaju tu prednost da rade na proizvoljnoj platformi, pa se logički font može koristiti bez potrebe provere njegove dostupnosti. Ipak, izgled logičkog fonta može varirati od platforme do platforme • Korišćenje fizičkih fontova pruža veću fleksibilnost, ali font koji se koristi mora biti dostupan na platformi na kojoj se izvršava kod. • Stilovi se mogu i kombinovati OR-ovanjem ili sabiranjem pošto je svaki stil jednobitni integer. Ako želimo da my. Font bude i BOLD i ITALIC: Font my. Font = new Font("Serif", Font. ITALIC + Font. BOLD, 12); 50
Fontovi • Stil i veličina postojećeg Font objekta mogu se dobiti metodima get. Style() i get. Size(). Oba vraćaju vrednost tipa int. • Može se testirati pojedinačni stil Font objekta sa: is. Plain(), is. Bold() i is. Italic(). Svaki od ovih metoda vraća boolean vrednost koja ukazuje da li Font objekat ima taj stil ili ne. • Pre nego što kreiramo font koristeći ime fonta, treba da znamo da li je taj font dostupan na sistemu gde se naš kod izvršava. Za to treba koristiti metod get. All. Fonts() klase Graphics. Environment definisane u paketu java. awt. Tu klasu smo koristili i kada smo centrirali prozor. • Niz raspoloživih fontova možemo dobiti sa: Graphics. Environment e = Graphics. Environment. get. Local. Graphics. Environment(); Font[] fonts = e. get. All. Fonts(); 51
Fontovi • Referencu na Graphics. Environment objekat za tekuću mašinu dobijamo pozivom statičkog metoda get. Local. Graphics. Environment(). Zatim tu referencu koristimo za poziv metoda get. All. Fonts(). Taj metod vraća niz Font objekata koji se sastoji od onih fontova koji su dostupni na tekućem sistemu. Zatim možemo proveriti da li se u tom nizu nalazi font koji želimo da koristimo. Svaka od Font-instanci u nizu biće veličine 1 -point, a pošto je 1 point približno 1/72 inča, ili 0. 353 mm, tipično ćemo želeti da povećamo veličinu fonta. Za promenu veličine i/ili stila fonta, pozivamo metod derive. Font() za taj font. Ovaj metod ima 3 verzije od kojih svaka vraća novi Font objekat zadate veličine i/ili stila: derive. Font(int Style) kreira novi Font objekat sa zadatim stilom (PLAIN, BOLD, ITALIC ili BOLD+ITALIC) derive. Font(float Size) kreira novi Font zadate veličine derive. Font(int Style, int Size) kreira novi Font zadatog stila i veličine 52
Fontovi • primer, korišćenje poslednjeg fonta iz niza Font objekata za kreiranje ekvivalentnog 12 -point fonta: Font new. Font = fonts[fonts. length-1]. derive. Font(12. 0 f); • (postoji i 4. verzija derive. Font() metoda koja uključuje objekat tipa java. awt. geom. Affine. Transform) • Dobijanje Font objekta za svaki font u sistemu može biti vremenski zahtevan proces ako ima puno instaliranih fontova. Mnogo brža alternativa je dobiti imena fontova, a zatim koristiti jedno od njih za kreiranje Font objekta koji nam treba. Imena svih fontova sistema mogu se dobiti sa: Graphics. Environment e = Graphics. Environment. get. Local. Graphics. Environment(); String[] font. Names = e. get. Available. Font. Family. Names(); 53
Font metrika • Svaka komponenta ima metod get. Font. Metrics() koji možemo koristiti za dobijanje metrike fonta (font metrics) – obilja podataka o dimenzijama fonta. Font objekat se prosledi metodu, a on vraća objekat tipa Font. Metrics koji koristimo da dobijemo podatke za određeni font. • primer: Font. Metrics metrics = prozor. get. Font. Metrics(prozor. get. Font()); • sada se mogu pozivati Font. Metrics metodi za objekat metrics da bi se dobile osnovne dimenzije fonta. 54
Swing komponente • Sve Swing komponente imaju JComponent klasu kao baznu, a ona nasleđuje klasu Component i dodaje joj sledeće mogućnosti: – podrška pluggable look-and-feel za komponente, dopuštajući programsku promenu look-and-feel ili implementiranje sopstvenog look-and-feel za sve komponente koje se prikazuju – podrška tooltip-ovima – tooltip je poruka koja opisuje svrhu komponente kada se kursor miša zadrži iznad nje. Tooltip-ovi su definisani klasom JTooltip. – podrška automatskog skrolovanja liste, tabele ili drveta kada se komponenta povlači mišem – specijalna debugging podrška za grafiku, koja obezbeđuje usporeno iscrtavanje tako da možemo da vidimo šta se dešava – klase komponenata se jednostavno nasleđuju, tako da kreiramo sopstvene specijalizovane komponente • Sve klase za Swing komponente definisane su u javax. swing paketu 55 i imena svih tih klasa počinju slovom J.
Dugmad • Swing klase za dugmad u paketu javax. swing definišu različite vrste dugmadi kojima se operiše klikom miša. • Klase za dugmad imaju Abstract. Button klasu kao baznu JComponent Abstract. Button JToggle. Button JCheck. Box • JButton JRadio. Button Klasa JButton definiše regularni pushbutton, npr. OK/Cancel dugme u dijalogu, ili u toolbar-u gde dugmad mogu biti alternativa stavkama menija 56
Dugmad • JTool. Bar klasa se koristi zajedno sa JButton klasom za kreiranje toolbar-a koji sadrži dugmad. • JToggle. Button klasa definiše dugme sa dva moguća stanja: pritisnuto i nije pritisnuto i dve specijalizovanije verzije definisane sa JCheck. Button i JRadio. Button. • Radio dugmad definisana JRadio. Button objektima generalno operišu u grupi tako da samo jedno dugme može biti u stanju pritisnuto u svakom datom trenutku. Grupisanje se postiže dodavanjem JRadio. Button objekata Button. Group objektu koji vodi računa o stanju dugmadi u grupi. • JCheck. Box objekat je dugme sa kvadratnim checkbox-om sa leve strane. Klik na checkbox menja njegovo stanje iz čekiranog u otčekirano i obrnuto. • Sva dugmad mogu biti prikazana sa tekst labelom, ikonom ili sa oba. 57
Meniji • Swing komponente uključuju podršku pop-up ili kontekstnim menijima kao i menu bar-ovima. Klase koje definišu elemente menija: JComponent JMenu. Bar Abstract. Button JPopup. Menu JMenu. Item JRadio. Button. Menu. Item JMenu JCheck. Box. Menu. Item • Klasa JMenu. Bar definiše menu bar ( liniju menija ) koja se obično nalazi na vrhu prozora aplikacije. • JMenu objekat predstavlja objekat stavku najvišeg nivoa menija koja se nalazi na menu bar-u i kada se klikne na nju, ona se razvije u listu stavki menija 58
Meniji • Stavke u meniju definisane su klasom JMenu. Item. • Klasa JPopup. Menu definiše kontekstni meni koji je tipično implementiran tako da se pojavi na tekućoj poziciji kursora pri desnom kliku na miša • JCheck. Box. Menu. Item komponenta je stavka menija sa checkbox-om koji je štikliran (čekiran) kada je stavka izabrana • JRadio. Button. Menu. Item klasa definiše stavku menija koja je deo grupe u kojoj samo 1 stavka može biti selektovana u jednom trenutku. Grupa se kreira dodavanjem JRadio. Button. Menu. Item objekta Button. Group objektu 59
Tekstualne komponente • Mogućnosti Swing tekstualnih komponenata su velike. • Klase javax. swing paketa koje predstavljaju tekstualne komponente ( kao i sve Swing komponente imaju klasu JComponent kao baznu ): JComponent JEditor. Pane JText. Component JLabel JText. Pane JText. Field JText. Area JFormatted. Text. Fieldž • Najosnovnija tekstualna komponenta je JLabel objekat. JLabel komponenta je pasivna i ne reaguje na ulazne događaje (input events), pa se ne može editovati 60
Tekstualne komponente • JText. Field komponenta izgleda slično kao labela u smislu da prikazuje 1 liniju teksta, ali nju je moguće editovati. • JFormatted. Text. Field komponenta je JText. Field komponenta koja kontroliše i formatira podatke koji se prikazuju ili unose. U mnogim situacijama može obezbediti automatsko formatiranje ( npr. automatski prikaz Date objekta kao datuma ) • JText. Area klasa definiše komponentu koja dopušta editovanje više linija teksta. Ova komponenta ne podržava skrolovanje direktno, ali dodavanje scrollbar-ova je jednostavno smeštanjem JText. Area komponente u JScroll. Pane kontejner. • JEditor. Pane i JText. Pane relativno jednostavno omogućuju sofisticiranije editovanje. JEditor. Pane podržava editovanje običnog teksta, teksta u HTML i RTF (Rich Text Format). JText. Pane klasa nasleđuje JEditor. Pane i omogućuje ugradnju slika ili drugih komponenata u tekst kontrolisano od strane komponente. 61
Ostale Swing komponente • Ostale Swing komponente koje ćemo koristiti po pravilu uključuju JPanel komponentu. • Klasa JPanel definiše nešto poput fizičkog panoa koji koristimo kao kontejner za grupisanje skupa komponenata • Npr. možemo koristiti 2 JPanel objekta za podršku dvema odvojenim grupama JButton komponenata u content pane prozora aplikacije. • JList i JTable komponente su takođe vrlo korisne. • JTable komponenta automatski vodi računa o preuređivanju kolona kada se neka kolona prevuče mišem na novu poziciju • U principu, svakoj komponenti se može dodati granica (border), a paket javax. swing. borders sadrži 8 klasa koje predstavljaju različite vrste granica koje se mogu koristiti za komponente. Međutim, možemo takođe smestiti komponentu kojoj želimo dodati granicu u JPanel kontejner i dodati granicu tom JPanel objektu ( JPanel objekti se prilično koriste ) 62 • Ovo nije potpun spisak svih Swing komponenata.
Korišćenje kontejnera • Kontejner je proizvoljna komponenta tipa koji ima Container klasu kao baznu, pa su sve Swing komponente kontejneri. • Klasa Container je direktna bazna klasa za klasu Window i obezbeđuje mogućnost prozora da sadrži druge komponente. • Pošto je klasa Container apstraktna klasa, ne možemo kreirati njene instance. Ali, objekti njenih potklasa ( Window, JFrame ili JDialog ) nasleđuju od nje mogućnost da sadrže druge komponente. • Kontejner ne može sadržati objekat klase Window ili neke od njenih potklasa. Objekat svake druge klase izvedene iz klase Component može se dodati kontejneru • Komponente unutar kontejnera prikazuju se unutar površi koju kontejner zauzima na ekranu. • Naravno, da bi sadržane komponente bile vidljive, sam kontejner mora biti prikazan, pošto kontejner efektivno poseduje svoje 63 komponente
Korišćenje kontejnera • Kontejner takođe kontroliše kako su raspoređene ugrađene komponente, i to pomoću objekta koji se naziva layout manager. • Razmotrimo najpre osnovne metode definisane u klasi Container koji su dostupni svim kontejnerima. • Za informacije o komponentama sadržanim u Container objektu možemo koristiti sledeće metode: int get. Component. Count() vraća broj komponenti sadržanih u tekućem kontejneru Component get. Component(int index) vraća komponentu identifikovanu vrednošću index. Vrednost index predstavlja indeks niza pa mora biti iz odgovarajućeg opsega, inače Array. Index. Out. Of. Bounds. Exception Component[] get. Components() vraća niz svih komponenata sadržanih u tekućem kontejneru Takođe, moguće je dobiti referencu na komponentu koja sadrži datu tačku unutar površi koju zauzima kontejner pozivom metoda get. Component. At() sa x i y koordinatama tačke kao argumentima. Ako više od jedne komponente sadrži tačku, biće vraćena komponenta čiji je 64 indeks u kontejneru najbliži 0.
Korišćenje kontejnera • Ako imamo Container objekat, content, npr. content pane JFrame prozora, možemo iterirati kroz komponente u njemu sa: Component component = null; int num. Components = content. get. Component. Count(); for( int i=0; i<num. Components; i++){ component = content. get. Component(i); // Radimo nesto sa komponentom … } • ovim se komponente kontejnera dobijaju 1 po 1 u for-petlji. Alternativno, možemo ih dobiti iz kontejnera i sve odjednom: Component[] komponente = content. get. Components(); for(Component komponenta: komponente){ // Radimo nesto sa komponentom … } 65
Dodavanje komponenata u kontejner • Komponente koje dodamo u kontejner pamte se u nizu unutar Container objekta. Veličina tog niza se povećava po potrebi kako bi se niz prilagodio svim prisutnim komponentama • Za dodavanje komponente u kontejner koristi se metod add(). Klasa Container definiše sledeće 4 verzije (overloading) add() metoda: Component add(Component c) dodaje komponentu c na kraj liste komponenata smeštenih u kontejner. Povratna vrednost je c. Component add(Component c, int index) dodaje komponentu c listi komponenata u kontejneru na poziciju zadatu vrednošću index. Ako je index -1, komponenta se dodaje na kraj liste. Ako nije -1, vrednost index mora biti manja od broja komponenata u kontejneru i >= 0. Povratna vrednost je c. void add(Component c, Object constraints) dodaje komponentu c na kraj liste komponenata smeštenih u kontejner. Relativna pozicija komponente u odnosu na kontejner određena je drugim parametrom void add(Component c, Object constraints, int index) slično kao prethodni metod, ali se komponenta ne dodaje na kraj liste već na zadatu poziciju. Za index važi isto što i za drugu verziju metoda add(). 66
Dodavanje komponenata u kontejner • Primetimo da dodavanje komponente prvom verzijom metoda add() ne izmešta komponente koje su već u kontejneru • Kada dodamo komponentu na zadatu poziciju, ostale komponente se pomere tako da naprave prostora za novu komponentu • Međutim, komponenta se u jednom trenutku može nalaziti samo u jendom kontejneru. Dodavanje komponente koja je već u nekom kontejneru u neki drugi kontejner ukloniće tu komponentu iz tog drugog kontejnera • Pre nego što pokušamo da dodamo komponente u kontejner, moramo razumeti ograničenja (constraints) koja se pojavljuju u nekim od add() metoda i pogledati kako se kontroliše raspored komponenata u kontejneru. 67
Layout menadžeri kontejnera • Kao što je već rečeno, objekat zvani layout manager određuje način na koji su komponente raspoređene u kontejneru • Svi kontejneri imaju default layout manager, ali po potrebi možemo izabrati i neki drugi. Mnoge klase layout manager-a nalaze se u paketima java. awt i javax. swing. Moguće je i kreirati sopstvene layout maganer-e, ali to je izvan granica ovog kursa • layout manager za kontejner određuje poziciju i veličinu svih komponenata u kontejneru, pa generalno veličinu i poziciju takvih komponenti ne treba sami da menjamo, samo prepustimo layout manager-u da se pobrine za to. • Pošto sve klase koje definišu layout manager-e implementiraju Layout. Manager interfejs, možemo koristiti promenljivu tipa Layout. Manager za smeštanje bilo koje od njih, ako je potrebno 68
Layout manager klase – neke od njih Flow. Layout smešta komponente u uzastopne redove kontejnera uklapajući u 1 red što je moguće više komponenti i prelazeći u novi red kada je prethodni pun. Ovo funkcioniše na isti način na koji text editor smešta reči u liniju. Primarna svrha ovog manager-a je za raspoređivanje dugmadi, ali može se koristiti i za druge komponente. To je default layout manager za JPanel objekte. Border. Layout za Card. Layout smešta komponente uz svaku od 4 ivice kontejnera i u centar. Komponenta u centru popunjava sav raspoloživi prostor. Ovo je default layout manager content pane u JFrame, JDialog i JApplet objektu. smešta komponente u kontejneru jednu na drugu – poput špila karata. U svakom trenutku vidljiva je samo komponenta koja je na vrhu. Grid. Layout smešta komponente u pravougaonu mrežu čiji broj vrsta i kolona sami zadamo Grid. Bag. Layout takođe smešta komponente po vrstama i kolonama, ali dužina vrsta i kolona može varirati. Komplikovan layout manager koji pruža dosta fleksibilnosti Box. Layout smešta komponente ili u vrstu ili u kolonu. Po potrebi, komponente se skraćuju da bi se uklopile. Ovo je default layout manager za Box kontejnersku klasu. Spring. Layout dopušta da pozicija komponenti bude definisana "oprugama" ili "dijagonalama" fiksiranim za ivicu kontejnera ili drugu komponentu u kontejneru 69
Layout manager klase • Box. Layout, Spring. Layout i Box. Layout klase definisane su u paketu javax. swing, dok su ostale navedene klase iz paketa java. awt. • Zašto su uopšte potrebni layout manager-i ? • Zašto se komponente ne bi prosto smeštale na neku datu poziciju u kontejneru? • Glavni razlog je da bi GUI elementi našeg Java programa bili ispravno prikazani u svakom mogućem Java okruženju. • Layout maganer-i automatski podešavaju veličinu i pozicije komponenata tako da se uklope u raspoloživi prostor. • Ako se fiksira veličina i pozicija svake od komponenata, može se desiti da se one preklope ako se smanji površ ekrana dostupna našem programu 70
layout manager • Da bismo postavili layout manager za Container objekat, možemo pozvati njegov set. Layout() metod. • Npr. možemo promeniti layout manager za Container objekat prozor tipa JFrame, tako da umesto default Border. Layout to bude Flow. Layout: Flow. Layout flow = new Flow. Layout(); prozor. get. Content. Pane(). set. Layout(flow); • !!! Upamtiti da komponente koje želimo da budu prikazane u klijent oblasti JFrame objekta treba dodati u njegov content pane. Isto važi i za JDialog i JApplet objekte. • U stvari, ako koristimo add() metod za JFrame, JDialog ili JApplet objekat kako bismo dodali komponentu, on će biti preusmeren na content pane i sve će ispasti kako treba. Ova olakšica je zbog konzistentnosti sa sličnim AWT komponentama. Ipak, za neke druge operacije – poput postavljanja boje pozadine npr. mora se pozivati baš metod koji pripada content pane objektu. Iz tog razloga, bolje je sve operacije eksplicitno izvršavati nad content pane nego se oslanjati na redirekciju. • Kod nekih kontejnera, layout manager se može postaviti u konstruktoru za taj kontejner. 71
Flow layout manager – smešta komponente u red i kada se red popuni, nastavlja u narednom redu – default pozicioniranje reda komponenata je centrirano u odnosu na kontejner i default orijentacija je sleva na desno – postoji 5 mogućih opcija za pozicioniranje reda koje zadajemo konstantama tipa int definisanim u klasi Flow. Layout. To su: LEFT, RIGHT, CENTER (default), LEADING i TRAILING – po default-u, komponente u redu razdvojene su prazninom od 5 jedinica, a isto toliko su udaljeni i uzastopni redovi – flow layout manager je vrlo jednostavan za upotrebu • primer: Test. Flow. Layout. java – Ovaj layout manager se primarno koristi za aranžiranje nekoliko komponenata čija je relativna pozicija nebitna 72
Test. Flow. Layout. java • red dugmadi je centriran, da bismo to videli možemo pomoću miša povlačenjem ivica prozora da mu smanjimo veličinu • Svako dugme je postavljeno na njegovu prioritetnu veličinu, koja je prilagođena tekstu labele Flow. Layout flow = new Flow. Layout(Flow. Layout. LEFT); • flow layout manager sada levo uravnava svaki red komponenata 73
Promena razmaka • default razmak je 5 piksela između komponenti u redu, kao i između uzastopnih redova. • Možemo izabrati vrednosti za horizontalne i vertikalne razmake korišćenjem još jedne verzije Flow. Layout konstruktora: npr. horizontalni razmak 20 piksela, a vertikalni 30 piksela Flow. Layout flow = new Flow. Layout(Flow. Layout. LEFT, 20, 30); • Razmake između komponenata i redova možemo postaviti i eksplicitno, pozivom metoda set. Hgap() i set. Vgap(), npr. flow. set. Hgap(35); // postavlja horizontalni razmak na 35 piksela • Ne dajmo da nas ovo zavede. Ne možemo dobiti različit razmak između komponenata postavljanjem razmaka pre svakog dodavanja komponente u kontejner. Poslednje vrednosti za razmake između komponenata koje postavimo za layout manager biće primenjene na sve komponente u kontejneru. Ovo zbog toga što se layout dinamički reizračunava svaki put kada se prikaže kontejner. Mnogo različitih događaja može zahtevati ponovni prikaz kontejnera u toku 74 izvržavanja aplikacije.
promena razmaka • Metodi get. Hgap() i get. Vgap() vraćaju tekuće podešavanje za horizontalni i vertikalni razmak kao vrednost tipa int. • Inicijalna veličina prozora aplikacije određena je vrednostima koje prosledimo set. Bounds() metodu za JFrame objekat. • Ako želimo da prozor ima veličinu koja se prilagođava komponentama koje on sadrži, možemo pozvati metod pack() za Frame objekat. • Dodajmo sledeću liniju neposredno ispred poziva set. Visible(): prozor. pack(); 75
Primer: Test. Applet. java • Apletu kreiranom kao JApplet objekat komponente se dodaju na isti način kao i za JFrame prozor aplikacije. • Možemo to proveriti dodavanjem nekoliko dugmadi primeru apleta. • Možemo probati i Font objekat i dodati dugmadima ivicu • primer: Test. Applet. java • Da bismo pokrenuli aplet, potreban nam je. html fajl koji sadrži: <APPLET CODE="Test. Applet. class" WIDTH=300 HEIGHT=200> </APPLET> • Ovo određuje širinu i visinu apleta • Možemo sačuvati fajl kao Test. Applet. htm • Nakon što iskompajliramo source kod apleta koristeći javac, možemo ga izvršiti koristeći appletviewer program unevši narednu komandu u folder koji sadrži. htm fajl i. class fajl: 76 appletviewer Test. Applet. htm
Aplet • Aplet se izvršava prilično drugačije od Java programa i to nije nezavisan program. browser (u ovom slučaju appletviewer) započinje i kontroliše izvršavanje apleta • Aplet ne zahteva main() metod • Da bi izvršio aplet, browser prvo kreira instancu naše aplet klase, Test. Applet, a zatim poziva metod init() za nju. • Ovaj metod je nasleđen od klase Applet ( bazne za JApplet ) i tipično ga predefinišemo (override) da bismo obezbedili sopstvenu inicijalizaciju • Primetimo kako je veličina svakog dugmeta automatski podešena tako da se prilagodi labeli dugmeta. • Oba fonta u ovom primeru su logička, pa će biti dostupna na svakom sistemu. Ako hoćemo da probamo fizičke fontove, izaberimo 2 od instaliranih na našem sistemu • Dugmad izgledaju mnogo bolje sa podignutim ivicama. Ako hoćemo da izgledaju "potopljena", kao argument konstruktora zadamo 77 Bevel. Border. LOWERED
Border Layout Manager • Namenjen je da smesti do 5 komponenata u kontejner • Sa ovim layout manager-om možemo smestiti komponente uz svaku od 4 ivice kontejnera i u njegov centar • Samo 1 komponenta može biti na svakoj od ovih pozicija. Ako dodamo komponentu na poziciju koja je već zauzeta, prethodna komponenta se uklanja • Ivica se izabira zadavanjem ograničenja koje može biti NORTH, SOUTH, EAST, WEST ili CENTER. Sve ovo su final static konstante definisane u klasi Border. Layout. • Ograničenja se ne mogu zadati u Border. Layout konstruktoru pošto različito ograničenje treba primeniti na svaku komponentu. Poziciju svake komponente u kontejneru zadajemo kada je dodajemo add() metodom. • menjamo prethodni primer aplikacije tako da dodamo 5 dugmadi u content pane prozora aplikacije pomoću border layout manager-a 78
Primer: Test. Border. Layout. java • primer: Test. Border. Layout. java • Komponente raspoređene border layout manager-om se šire tako da popune raspoloživ prostor u kontejneru • "NORTH" i "SOUTH" dugmad imaju punu širinu prozora, a "EAST" i "WEST" imaju visinu koja je preostala nakon što su "NORTH" i "SOUTH" dugmad zauzela svoja mesta • To uvek tako funkcioniše, bez obzira na redosled kojim dodajemo dugmad – "NORTH" i "SOUTH" komponente zauzimaju celu širinu kontejnera, a "CENTER" komponenta zauzima preostali prostor. Ako nema "NORTH" i "SOUTH" komponenata, "EAST" i "WEST" 79 komponente će se proširiti do pune visine kontejnera
Test. Border. Layout. java • Širina dugmadi "EAST" i "WEST" određena je prostorom neophodnim za smeštanje labela dugmadi. Slično, dugmad "NORTH" i "SOUTH" određena su visinom karaktera u labelama • Možemo menjati prostor između komponenata prosleđivanjem argumenata Border. Layout konstruktoru – default razmaci su 0 • npr. možemo postaviti horizontalni razmak na 20 piksela i vertikalni na 30 piksela sa: content. set. Layout(new Border. Layout(20, 30)); • Kao kod flow layout manager-a, razmake možemo postaviti i individualno pozivom metoda set. Hgap() i set. Vgap() za Border. Layout objekat. Npr. Border. Layout border = new Border. Layout(); content. set. Layout(border); border. set. Hgap(20); • ovo postavlja horizontalni razmak između komponenata na 20 piksela i ostavlja vertikalni razmak na podrazumevanoj vrednosti – 0. • Tekuće vrednosti razmaka možemo dobiti sa get. Hgap() i get. Vgap(). 80
Card Layout Manager • Generiše stek komponenata koje se slažu jedna na drugu • Prva komponenta koju dodamo u kontejner biće na vrhu steka, i time vidljiva, a poslednja će biti na dnu • Card. Layout objekat možemo dobiti podrazumevanim konstruktorom, Card. Layout(), ili možemo zadati horizontalni i vertikalni razmak kao argumente konstruktora. U ovom slučaju, razmaci su između ivice komponente i granice kontejnera • primer, na apletu • Test. Card. Layout. java • zbog načina na koji funkcioniše card layout, neophodan je način interakcije sa apletom kako bi se prelazilo sa jedne komponente na drugu. To implementiramo omogućavanjem procesiranja događaja mišem. Taj kod sada neće biti objašnjavan 81
Test. Card. Layout. java • Kreiramo Card. Layout objekat, card, sa horizontalnim i vertikalnim razmacima od 50 piksela. • U init() metodu apleta: imamo 2 argumenta za • Prvi je referenca na komponentu koju dodajemo u kontejner • Korišćenje cart layout-a zahteva da svaku komponentu identifikujemo objektom neke klase koji prosleđujemo kao drugi argument metoda add(). Parametar metoda je tipa Object. • U ovom primeru, prosleđujemo String objekat kao drugi argument metoda add() ( koristimo proizvoljan string za identifikovanje svake komponente, koji se sastoji od stringa "Card" sa dopisanim rednim brojem dugmeta ) 82
Test. Card. Layout. java • Unutar petlje pozivamo metod add. Action. Listener() za svako dugme da bismo identifikovali aplet objekat kao objekat koji će obrađivati događaje generisane za dugme ( kao što je klik mišem na dugme ) • Kada kliknemo na dugme, poziva se metod action. Performed() za aplet objekat. On samo poziva metod next() za layout objekat da pomeri sledeću komponentu u nizu na vrh. • Argument next() metoda identifikuje kontejner kao Test. Card. Layout objekat koji se kreira kada aplet počne • Klasa Card. Layout ima druge metode koje možemo koristiti za izbor sa steka komponenata: void previous(Container parent) izabira prethodnu komponentu u kontejneru parent void first(Container parent) izbor prve komponente iz kontejnera parent void last(Container parent) izbor poslednje komponente iz kontejnera parent void show(Container parent, String name) izbor komponente iz kontejnera parent pridružene String objektu name. Ovo mora biti 1 od String objekata zadatih kada je metod add() pozivan za dodavanje 83 komponenata
Test. Card. Layout. java • Korišćenjem next() ili previous() metoda možemo uzastopno kružiti kroz komponente pošto je sledeća komponenta za poslednju prva, a komponenta pre prve je poslednja • String objekat koji smo zadali kada smo dodavali dugme u kontejner identifikuje dugme i možemo ga koristiti za prelaz na to dugme. • Npr. možemo preći na dugme pridruženo stringu "Card 4" pre prikazivanja apleta dodavanjem sledeće naredbe nakon petlje koja dodaje dugmad: card. show(content, "Card 4"); • ovo poziva show() metod za layout manager • prvi argument je kontejner, a drugi identifikuje komponentu koja treba da dođe na vrh, a time i onu koja je vidljiva kada se prikaže prozor 84
Grid Layout Manager • Aranžira komponente u pravougaonu mrežu unutar kontejnera • Postoje 3 konstruktora za kreiranje Grid. Layout objekta: Grid. Layout() kreira grid layout manager koji će komponente smestiti u 1 red (tj. 1 kolona po komponenti) bez razmaka između komponenata Grid. Layout(int rows, int cols) komponente se smeštaju u mrežu sa datim brojem vrsta/redova i kolona, takođe bez razmaka između komponenata Grid. Layout(int rows, int cols, int hgap, int vgap) -||- ali sa horizontalnim i vertikalnim razmakom između komponenata od hgap i vgap piksela, redom • U drugom i trećem konstruktoru možemo zadati da je broj vrsta ili broj kolona 0 ( ali ne oba ). Ako zadamo da je broj vrsta 0, layout manager će obezbediti onoliko vrsta u mreži koliko je potrebno da bi se smestile sve komponente koje dodamo u kontejner • Slično, postavljanje broja kolona na 0 označava proizvoljan broj kolona • Ako fiksiramo i broj vrsta i broj kolona, i dodamo više komponenti nego što mreža može da prihvati, broj kolona će se prikladno povećati 85 • primer: varijacija prethodnog primera: Test. Grid. Layout. java
- Slides: 85