128
Internacionalni univerzitet u Novom Pazaru Objektno programiranje Tema: PROGRAMSKI JEZIK JAVA -GRAFIČKI KORISNIČKI INTERFEJS (GUI)- Student:Semir Hodžić, Mensur Rebronja 1

Java GUI

  • Upload
    semirbp

  • View
    182

  • Download
    2

Embed Size (px)

Citation preview

Internacionalni univerzitet uNovom Pazaru

Objektno programiranje

Tema: PROGRAMSKI JEZIK JAVA

-GRAFIČKI KORISNIČKI INTERFEJS (GUI)-

Student:Semir Hodžić, Mensur Rebronja

Doc.dr.Zoran Lovreković

Novi Pazar, Oktobar 2012.

1

Sadržaj1 PROGRAMSKI JEZIK JAVA -GRAFIČKI KORISNIČKI INTERFEJS (GUI)....................3

1.1 Dugmad i događaji............................................................................................................4

1.2................................................................................................................................................5

1.3 Mesto događaja.................................................................................................................5

1.4 Checkbox i CheckboxGroup.............................................................................................6

1.5................................................................................................................................................7

1.6 Tekstualne komponente, lista izbora.................................................................................7

1.7 Iscrtavanje linija................................................................................................................9

1.8 Crtanje pravougaonika....................................................................................................12

1.9 Iscrtavanje ispunjenog  pravougaonika...........................................................................13

1.10 Brisanje pravougaonika...................................................................................................15

1.11 Elipse i kruznice..............................................................................................................16

1.12 Kôdovi tastera.................................................................................................................28

1.13 Modifikatori uz taster miša.............................................................................................32

1.14 Događaji vezani uz fokus................................................................................................33

1.15 Događaji vezani uz komponentu (Component Events)...................................................33

2 Kontrola razmeštaja komponenti............................................................................................37

2.1.1 Ručno pozicioniranje komponenti...........................................................................37

2.1.2 Implementacije LayoutManagera............................................................................38

2.1.3 Razmeštaj tipa FlowLayout.....................................................................................39

2.1.4 Podešavanje poravnanja za FlowLayout.................................................................40

2.1.5 Razdvajanje komponenti za FlowLayout................................................................42

2.1.6 Razmeštaj tipa BorderLayout..................................................................................42

2.1.7 Razmeštaj tipa CardLayout......................................................................................44

2.1.8 Upotreba CardLayout razmeštaja............................................................................47

2.1.9 Promena karata........................................................................................................48

2.1.10 Razmeštaj tipa GridLayout......................................................................................49

2.1.11 Razmeštaj tipa GridBagLayout................................................................................51

2.1.12 Specifikacije GridBagConstraints...........................................................................51

2.1.13 Atributi gridwidth i gridheight.................................................................................54

2.1.14 Atribut fill................................................................................................................54

2.1.15 Atributi ipadx i ipady...............................................................................................55

2.1.16 Atribut Insets...........................................................................................................55

2

2.1.17 Atribut anchor..........................................................................................................55

2.1.18 GridBagConstraints.CENTER GridBagConstraints.NORTH GridBagConstraints.NORTHEAST GridBagConstraints.EAST GridBagConstraints.SOUTHEAST GridBagConstraints.SOUTH GridBagConstraints.SOUTHWEST GridBagConstraints.WEST GridBagConstraints.NORTHWEST Pretpostavljena vrednost je GridBagConstraints.CENTER. U tekućem primeru to nije eksplicitno navedeno, jer su komponente dovoljno velike u odnosu na raspoložive površine, tako da je centrirana pozicija zadovoljavajuća........................................................................................................55

2.1.19 Atributi weightx i weighty.....................................................................................56

2.1.20 Šta je Container?......................................................................................................68

3 DIZAJN KORISNIČKOG INTERFEJSA UPOTREBOM Swing-a.....................................88

3

1 PROGRAMSKI JEZIK JAVA-GRAFIČKI KORISNIČKI INTERFEJS (GUI)

Paket Java AWT daje sve neophodne alate za izgradnju standardnog Windows GUI (graphical User Interface). Ekran u Windows-u, sva dugmad (buttons), klizači (scroll bars), dijalog prozori (dialog boxes) i ostali elementi ispisa i interakcije sa korisnikom čine grafičko okruženje i sve standardne komponente su dostupne u Java-i.

    komponente opis

dugme / Buttonpredmet kliktanja mišem, može se odrediti natpis i kontrolisati akcije nakon pritiskanja dugmeta

radni prostor / Canvas

ograničen prostor u kome se može crtati i pisati

Checkbox, checkboxGroup

opcije koje se mogu uključivati (štiklirati) ili isključivati; specifičnost CheckboxGroup vezana je za mogućnost uključivanja samo jedne opcije iz nekog skupa srodnih

lista za izbor opcije / Choice

liste sa kojih je moguće odabrati samo jednu od mogućih opcija

oznaka / Label označavanje koje se integriše sa ostalim GUI komponentamalista / List liste sa kojih je moguće odabrati više ponuđenih opcijapolje za unos teksta / TextField

prihvatanje jednolinijskog unosa korisnika

prostor za unos teksta / TextArea

prihvatanje veće količine unosa teksta

Layout i Panelkontrolišu pozicioniranje elemenata GUI-a, npr panelima se ekran može vertikalno podeliti tako da srednji panel upotrebi Lazout da bi podjednak prostor bio dodeljen poljima TextArea i prostoru za crtanje (Canvas).

4

1.1 Dugmad i događajiDefinisanje dugmadi kao GUI komponente:  Button dugme=new Button("Klikni");  add(dugme);

Prva linija kreira dugme i tekst njegove oznake. Druga linija postavlja dugme u prozor apleta. Ovaj kod se mora postaviti unutar metoda init() ili start().

  Event-handling (obrada događaja), konkretnije prepoznavanje korisnikovog klika na dugme, obrađuje se metodom action:   public boolean action(Event d, Object arg)     {           . . . akcije nakon pritiska na dugme          return (true);    }

Metod action() ima dva parametra koja se mogu ignorisati ako se koristi samo jedno dugme. Povratna vrednost metoda je Boolean tipa, te mora biti vracena vrednost true ili false bez obzira na kompleksnost akcije (koja postoji ili ne).   Primer koji na klik dugmeta reaguje ispisivanjem poruke na ekranu u vidu promene boje aktivnog pravougaonika.

 Pr.1

Upotrebom metoda repaint() u promenaBoje forsira se izvrsavanje metoda paint() koji se ne bi izvrsio sem u slucaju da se aplet ne zaustavi i ponovo pokrene (npr. prelaskom na neku drugu stranu).   import java.awt.*;   public class AkcijaDugme extends java.applet.Applet {      public void init() {      setBackground(Color.white);  /* postavka trenutno aktovnog pravougaonika */  /* Java dugmad dodaje na vrh prozora; u ovom slucaju pet dugmadi u prozor apleta*/     add(new Button("Crvena"));     add(new Button("Plava"));     add(new Button("Zelena"));     add(new Button("Bela"));     add(new Button("Crna"));   }

5

  public boolean action(Event evt, Object arg) {      /* metod odgovar ana svaki dogadjaj; u ovom programu to je klik na dugme koji proizvodi promenuBoje */     if (evt.target instanceof Button) {       promenaBoje((String)arg);       return true;     } else return false;   }

    /* promeniti pozadinu aktivnog pravougaonika u drugi boju kao reakciju na korisnikov klik na dugme */   void promenaBoje(String bojaIme) {     if (bojaIme.equals("Crvena")) setBackground(Color.red);     else if (bojaIme.equals("Plava")) setBackground(Color.blue);     else if (bojaIme.equals("Zelena")) setBackground(Color.green);     else if (bojaIme.equals("Bela")) setBackground(Color.white);     else setBackground(Color.black);

    repaint();        /* zbog repaint() izvrsava se paint() */   } }

1.2

1.3     Mesto događajaAko postoji više od jednog dugmeta ili drugih komponenti, mora se ispitati događaj da bi se saznale preciznije akcije događaja. Ovo se može uraditi preko Event parametra metoda action(). Taja parametar sadrži objekat target,klase Object, koji sadrži naziv komponente na koju je korisnik kliknuo ili ne neki drugi način uticao. Potrebno je samo ga uporediti sa nazivom dugmeta ili druge komponente. public boolean action(Event evt, Object arg) {      /* metod odgovar ana svaki dogadjaj; u ovom programu to je klik na dugme koji proizvodi promenuBoje */     if (evt.target instanceof Button) { Nije značajno što evt.target pripada klasi Object, jer klasa Button je podklasa od Object.

Moguće je izvršito modifikaciju ovog programa tako što će klik na jedno dugme promeniti boji i dekativirati to dugme, a aktivirati ostale dugmiće. Aktiviranje i deaktiviranje dugmića postiže se metodom setEnabled().  Npr aktiviranje zelenog dugmeta:             Crvenodug.setEnabled(false); Zelenodug.setEnabled(true);

   .....   Button Crvenodug, Zelenodug;   Color crvena=Color.red;   Color zelena=Color.green;

6

   Color tekuci=crvena;    public void init()    {   Crvenodug=new Button("Crveno");         Crvenodug.setEnabled(false);        Zelenodug=new Button("Zeleno");        add(Crvenodug);  add(Zelenodug);        tekuci=crvena;    } ..... Uraditi ovu modifikaciju za vežbu, tj. 1. Napisati aplet kojim se iscrtava prozor koji će inicijalno imati tri dugmeta sa natpisima crveno, zeleno, plavo. Kada se klikne na neko od dugmeta, promeniti pozadinsku boju aktivnog pravougaonika, deaktivirati to dugme, a druga dva aktivirati.

1.4   Checkbox i CheckboxGroupimport java.awt.*; import java.awt.Font;

 public class Komp2 extends java.applet.Applet{     Font f = new Font("TimesRoman", Font.BOLD, 22);

  public void init(){      setFont(f);      add(new Checkbox("KokaKola"));      add(new Checkbox("Sprite"));      add(new Checkbox("Vino"));      add(new Checkbox("Fanta"));      add(new Checkbox("Tonic", null, true));      add(new Checkbox("Sok-narandza"));

     add(new Label("Sledi primer sa radio-dugmadima"));      CheckboxGroup  grupa=new CheckboxGroup();      add(new Checkbox("Plava", grupa, false));      add(new Checkbox("Crvena", grupa, false));      add(new Checkbox("Zelena", grupa, true));      add(new Checkbox("Bela", grupa, false));      }  }

 Pr. 2 

7

Polja za uključivanje/isključivanje opcija se koriste bilo kao pojedinačni (Checkbox objekti), bilo kao grupa (u okviru CheckboxGroup objekta) na vrlo sličan način. Razlika je u mogućnosti izbora koja se nudi korisniku.  1.  Checkbox  objekti se mogu ukljušiti ili isključiti nezavisno od stanaj ostalih na toj strani  2.  Ako se koriste u okviru objekta CheckboxGroup  može biti isključeno samo jedno polje Ovo se može videti i u primeru 2.

Checkbox objekti moraju biti deklarisani na nivou programa. U prozor smestaju metodima init() ili start(). Najjednostavnije je da se istovremeno deklarisu i definisu, npr.     Checkbox c=new Checkbox("Oznaka 1", false); Prvi parametar se odnosi na ispis oznake uz polje, a drugi parametar predstavlja pocetno stanje (tru se odnosi na ukljuceno, false na iskljuceno).   Parametar koji oznacava stanje  može se izostaviti, ali će u tom slučaju početno stanje checkbox-a biti isključeno.  Checkbox se, slično ostalim komponentama, dodaje u prozor sledećom linijom u metodu init():    add(c);

U slučaju da checkbox je deo grupe, onda se najpre mora kreirati CheckboxGroup objekat:   CheckboxGroup  g=new CheckboxGroup();   Checkbox c1=new Checkbox("Oznaka 0", g, true);    Dakle, pri kreiranju checkbox-a c1, drugi parametar je naziv CheckboxGroup objekta. Samo jedan checkbox iz grupe moze imati treci parametar true.

Pomocu metoda action() moze se prepoznati dogadjaj kada korisnik klikne na neki checkbox, tj. moze se ispitati parametar Event objekta target  i tako saznati izabrani checkbox. Moguce je, sa druge strane, proveriti stanje ukljucenosti checkbox-a i tako saznati izabrani checkbox. To se radi metodom getState():   if (c.getState() == true) akcija za izabranu Oznaku 1; ili   boolean bStanje;      bStanje= c.getState();      if (bStanje) akcija za izabranu Oznaku 1;

Kod checkbox grupe se postavlja pitanje koji od checkbox-ova je uljucen metodom getSelectedCheckbox(). Povratna vrednost daje checkbox objekat, npr.       if (g.getSelectedCheckbox()==c1)  naziv=="Oznaka0";     else if (g.getSelectedCheckbox()==c3)  naziv=="Oznaka2";  

1.5

1.6     Tekstualne komponente, lista izboraimport java.awt.*; import java.awt.Font;

8

 public class Komp3 extends java.applet.Applet{     Font f = new Font("TimesRoman", Font.BOLD, 22);

  public void init(){      setFont(f);

     Choice c = new Choice();

     c.addItem("Jabuka");      c.addItem("Kruska");      c.addItem("Kajsija");      c.addItem("Sljiva");      c.addItem("Jagoda");      add(c);

     /* polja koja prihvataju unos korisnika: */      add(new TextField());      add(new TextField(30));      add(new TextField("Unesite Vase ime ovde"));      add(new TextField("Ovo je probni tekst", 6));      TextField tf= new TextField(20);      tf.setEchoCharacter('&');      add(tf);      add(new TextField("Pera, Mika, Laza"));      }  }

 Pr.3

Choice objekat predstavlja padajucu listu iz koje korisnik moze izabrati samo jednu opciju. List objekat predstavlja listu (sa ili bez klizaca) iz koje korisnik moze izabrati vise opcija istovremeno. Svaki Choice ili List objekat je jedinstvena komponenta i opcije za izbor su njegov sastavni deo. Najjednostavniji Choice ovbjekat se moze definisati ovako:    Choice c= new Choice();    c.addItem("Opcija 1");      c.addItem("Opcija 2");    add(c);  /* postavlja choce listu u aplet, prozor*/

Opcije za izbor se ispisuju redom koji prati redosled odgovarajucih addItem() poziva. Istim redosledom su sacuvane i unutar Choice objekta i moze im se direktno pristupiti preko odgovarajuceg indeksa, pocev od indeksa sa vrednosti 0. Na primer, da bi se opcija "Opcija 2" postavila kao podrazumevan izbor, upotrebi se metod select sa paramnetrom koji odgovara indeksu opcije 2 u Choice objektu, tj.   c.select(1);

9

Nakon sto je korisnik odabrao neku od ponudjenih opcija, moze se ocitati vrednost indeksa da bi se saznalo koja je izabrana opcija:   izabrana=c.getSelectIndex();

Ali, indeks ima i siru upotrebu. Koristi se za usmeravanje tok aprograma ili postavljanje vrednosti neke druge promenljive. Npr.   switch (c.getSelectIndex())     {          case 0: ...akcija za opciju 1 ...; break;          case 1: ...akcija za opciju 2 ...; break;       ...    }   TextField i TextArea  su podklase klase TextComponent. Dakle, one sadrže sve metode svojih nadklasa, ali i neke sopstvene metode.  Pri definisanju novog TextField objekta, mogu se upotrebiti sledeći konstruktori: new  TextField()   iza kog se moraju u programu upotrebiti metodi setText() ili setColumns() da bi se precizirala velicina new TextField(int)  gde vrednost tipa int odredjuje sirinu teksta new TextField(String) koji kreira polje u kome je upisan taj string new TextField(String, int) koji ogranicava sirinu polja na int vrednost i u njega upisuje dati string

TextArea objekti imaju slican skup konstruktora, ali se navode dve int vrednosti koje odredjuju njegovu velicinu u redovima i kolonama. Postoji i peti konstruktor new TextArea(String, int, int, int) gde poslednja vrednost tipa iny kontrolise pojavljivanje klizaca (1 ziskljucuje vertikalni klizac, 2 iskljucuje horizontalni klizac, 3 iskljucuje oba klizaca).

Koordinatni sistem Java koristi standardni, dvodimenzionalni sistem za računarsku grafiku. Prvi vidljivi piksel u gornjem levom uglu apletove pozadine je tačka (0, 0). Koordinate se povecavaju prema desno i nadole.

Crtanje se u Javi obavlja pomocu objekata klase java.awt.Graphics. Graficki objekt se daje kao argument metodi paint(Graphics g) koju klasa java.applet.Applet nasledjuje od klase java.awt.Container.  Sve sto bude receno  o crtanju u apletima vazi i za objekte kao sto su paneli, okviri, dugmici, pozadine itd. Iscrtavanje se uglavnom obavlja u metodu paint(). Iscrtavanje se može izvoditi direktno na apletu ili na radnoj površini koje će zbog svojih specifičnosti biti obrađeno kasnije. Svaki objekt tipa Graphics ima svoj vlastiti koordinatni sistem i metode za crtanje stringova, linija, pravougaonika, krugova, poligona i tako dalje. Crtanje u Javi počinje od pojedinačnog objekta tipa Graphics. Pristup tom objektu ostvaruje se metodom paint(Graphics g) u apletu.. Primer poziva metode za crtanje: g.drawString("Hello World", 0, 50) --------------------------------------------------------------------------------

10

1.7 Iscrtavanje linija

Za crtanje prave linije poziva se metod drawline() cija  sintaksa je:

public abstract void drawLine(int x1,                               int y1,                               int x2,                               int y2)

Poziva se ovako:

g.drawLine(x1, y1, x2, y2)

Pri tome su (x1, y1) i (x2, y2) krajnje tacke linije, a g je objekt tipa Graphics pomocu kog se iscrtava linija. Primer koji iscrtava liniju dijagonalno preko appleta.

import java.applet.*; import java.awt.*;

public class Dijagonala extends Applet {

 public void paint(Graphics g) {

    g.drawLine(0, 0, this.getSize().width, this.getSize().height);

 }

}

<APPLET code="Dijagonala.class" HEIGHT="200" WIDTH="200"> </APPLET>  

Klasa Graphics sadrži nekoliko metoda za iscrtavanje i sve one imaju ograničenja poput:   debljina linije je debljina tačke

  objekti se iscrtavaju u tekućoj boji

No, metodi su sasvim dovoljni za dijagrame, isticanje teksta, jednostavne animacije,...

11

Primer koji iscrtava na apletu tanku liniju od pozicije koordinatnog početka do pozicije koja je od nje udaljena 100 tačaka desno i 50 tačaka nadole. Takođe u primeru se vrši i scrtavanje deblje linije, tako što se uz osnovnu liniju iscrta još nekoliko linija.

   import java.awt.*;    import java.applet.*;

   public class TankaDebelaLinija extends Applet {

 public void paint(Graphics g) {

    g.drawLine(0, 0, 100, 50);  /* iscrtava osnovnu liniju od (0,0) do (100, 50) */

   g.setColor(new Color(255,0,0)); /* metod obradjen u 5. nastavku-metod koji podesava tekucu                                        boju objekta pre njegovog iscrtavanja; zadaje se kao triplet intenziteta                                        boja u RGB modelu */

  g.drawLine (50,75,200,25);   g.drawLine (50,75,200,26);  /* druga naredba se koristi da pojaca ispis iz prethodne naredbe*/

 g.setColor(new Color(0,255,0)); /* zelena*/

  for (int y1=120; y1<130; y1++)       g.drawLine(100, y1, 200, y1+20); /* uz osnovnu linju iscrtavanje se pojacava sa dodatnih  9 linija*/  }

}  

Primer koji kreira animaciju u formi linije koja rotira oko centra (120,120) i iscrtava krug. Matematički model zahteva da se uoči da pri ma kom uglu, poluprečnik se izdvaja kao hipotenuza trougla čije katete se prostiru od centra kruga do x, y koordinata neke tačke na kružnici.    

x= (int) (java.lang.Math.cos(ugao)*100) + 120; /* 100=duzina linije, poluprecnika;                                                                                    (120, 120) koordinate centra*/  

12

   import java.awt.*;    import java.applet.*;

   public class TragRotacije extends Applet {

          Color bela=new Color(180,255,255); /* nije bas (255,255,255) ali ostavlja trag*/           Color crna=new Color(0,0,0);           public void paint(Graphics g) {             int x,y; /*tacke granice kruga*/            double ugao=0;

           while(ugao < 6.28)   /* Java meri uglove u radijanima, 2PI radijana za 360 stepeni;                 while(ugao < 2*Math.PI) */ {                x= (int) (java.lang.Math.cos(ugao)*100) + 120;                  y= (int) (java.lang.Math.sin(ugao)*100) + 120;                  g.setColor(crna);                 g.drawLine(120,120,x,y);  /* iscrtava polaznu liniju */

                  /*prazna petlja za usporeni prikaz*/                     for(int pauza=0; pauza <20000; pauza ++)  ;

                 g.setColor(bela);                  g.drawLine(120,120,x,y);  /* novi polozaj*/                  ugao=ugao+0.01;             }             g.setColor(crna);             g.drawLine(120,120,220,120); /* ponovo se iscrtava da prikaze krajnji polozaj*/

     }

}

 --------------------------------------------------------------------------------

1.8 Crtanje pravougaonika

Pravougaonik se iscrtava pomocu objekta g iz klase Graphics i metode drawRect() cija je sintaksa:

public void drawRect(int x,                      int y,                      int width,                      int height)

Poziva se ovako:

13

public void drawRect(x, y, width, height)

Prva dva argumenta su koordinate gornjeg levog ugla pravougaonika, dok su ostala dva njegova sirina i visina.

Primer koji  iscrtava pravougaonik oko appleta.

import java.applet.*; import java.awt.*;

public class Pravougaonik extends Applet {

  public void paint(Graphics g) {

    g.drawRect(0, 0, this.getSize().width - 1, this.getSize().height - 1);

  }

}

Znamo da getSize().width je sirina pravougaonika, a getSize().height njegova visina. Zasto se onda pravougaonik iscrtava samo do getSize().height-1 i getSize().width-1?

Zato jer se levi gornji ugao nalazi u tacki (0, 0), a ne u (1, 1). To znaci da aplet velicine 100 x 200 piksela ukljucuje tacke s x-koordinatama izmedju 0 i 99, a ne izmedju 0 i 100. Slicno, y-koordinate su izmedju 0 i 199 ukljucivo, a ne izmedju 0 i 200.

Za crtanje kvadrata ne postoji posebna drawSquare() metoda. Kvadrat je pravougaonik jednakih stranica. --------------------------------------------------------------------------------

1.9 Iscrtavanje ispunjenog  pravougaonika

Metoda drawRect() crta prazan pravougaonik. Ako se zeli crtati kao  ispunjen, postoji metod fillRect() cija je sintaksa:

        public abstract void fillRect(int x,                               int y,                               int width,                               int height)

14

Primer koji  crta ispunjeni pravougaonik u centru apleta. Mora se razlikovati velicina pravougaonika od velicine appleta.

import java.applet.*; import java.awt.*;

public class PopuniCentriraj extends Applet {

  public void paint(Graphics g) {

    int appletVisina = this.getSize().height;     int appletSirina  = this.getSize().width;     int rectVisina   = appletVisina/3;     int rectSirina    = appletSirina/3;     int rectTop      = (appletVisina - rectVisina)/2;     int rectLeft     = (appletSirina - rectSirina)/2;

    g.fillRect(rectLeft, rectTop, rectSirina-1, rectVisina-1);

  }

}

<APPLET code="PopuniCentriraj.class" HEIGHT="50" WIDTH="40"> </APPLET>  

Primer koji iscrtava pravougaonik tanjih i ispod njega pravougaonik debljih ivica. (Metod drawRect iscrtava tanke linije kao stranice). Unutar pravougaonika ispisati stringove Prvi, Drugi pojacanim fontom velicine 14pt tipa SansSerif.

  Ako se zele deblje linije za ivice, onda se moze upotrebiti petlja i iscrtati jedan ispunjeni pravougaonik unutar drugog.

import java.applet.*; import java.awt.*;

public class Pravougaonik2 extends Applet {    Color crvena=new Color(0,255,255);    Color zuta=new Color(255,255,0);    Color crna=new Color(0,0,0);    Font niska=new Font("SansSerif", Font.BOLD, 14);

  public void paint(Graphics g) {

15

     g.setFont(niska); /* postavlja se opis fonta za tekuci objekat */      g.setColor (crvena); /* tekuca boja objekta */

      /* iscrtava se 5 uzastopnih pravougaonika; pocev od pravougaonika (50,50, 150, 75);         uzastopni pravougaonici su 2 piksel manji, a pocinju 1 piksel unutra i nadole, te se i od sirine    i od duzine oduzima 2*i */       for (int i=0; i<5; i++)           g.drawRect(50+i, 50+i, 150-2*i, 75-2*i);

     g.setColor(crna); /* postavlja se boja ispisa niske Prvi u 1. pravougaoniku */      g.drawString("Prvi",80,90);

     g.setColor(crvena); /* postavlja se boja ispisa pravougaonika 2 koji se nalazi  ispod pravougaonika 1*/      g.fillRect(50, 150,200,100);

      g.setColor(zuta); /* menja se unutrasnja boja, tj. ako je unutrasnja boja ista kao i pozadina, onda se barem vidi okvir pravougaonika*/      g.fillRect(60, 160,180,80);  

     g.setColor(crna); /* postavlja se boja ispisa niske Drugi u 2. pravougaoniku */      g.drawString("Drugi",100,200);

  }

}  

--------------------------------------------------------------------------------

1.10 Brisanje pravougaonika

Nacrtani pravougaonik moze se izbrisati metodom clearRect() cija je sintaksa: public abstract void clearRect(int x,                                int y,                                int width,                                int height)

Primer koji koristi metod clearRect() da bi prikazao bljesak pravougaonika na ekranu.

import java.applet.*; import java.awt.*;

public class Blink extends Applet {

16

  public void paint(Graphics g) {

    int appletH = this.getSize().height;     int appletW  = this.getSize().width;     int rectH   = appletH/3;     int rectW    = appletW/3;     int rectTop      = (appletH - rectH)/2;     int rectLeft     = (appletW - rectW)/2;

    for (int i=0; i < 1000000; i++) {       g.fillRect(rectLeft, rectTop, rectW-1, rectH-1);       g.clearRect(rectLeft, rectTop, rectW-1, rectH-1);     }

  }

}

Ovo nije nacin kako se u praksi radi animacija, no to je privremeno resenje  dok se ne nauci Java mehanizam rada sa nitima (thread). --------------------------------------------------------------------------------

1.11 Elipse i kruznice

Elipse i kruznice crtaju se pomocu metode drawOval(), a pune pomocu metode fillOval() cije su sintaksne signature: public abstract void drawOval(int x,                               int y,                               int width,                               int height)

public abstract void fillOval(int x,                               int y,                               int width,                               int height)

Argumenti ovih metoda predstavljaju koordinate gornjeg levog ugla, sirinu i visinu pravougaonika kom je elipsa upisana.

Nema posebne metode za crtanje kruznice. Kruznicu smatrati je elipsom upisanom u kvadrat.  

Primer apleta koji iscrtava elipsu i krug zajedno sa opisanim pravougaonicima oko njih.

17

import java.applet.*; import java.awt.*;

public class ElipsaKrugPravougaonik extends Applet {

  Color siva= new Color(160,160,160);   Color crna= new Color(0,0,0);

  public void paint(Graphics g) {

      g.drawRect(10,10,150,100);  /* pravougaonik 1*/      g.setColor(siva);      g.fillOval(10,10,150,100); /* ispunjena siva elipsa u pravougaoniku 1; stvarni parametri identicni         kao u pozivu metoda drawRect */

    g.fillRect(180,40, 100, 100);  /* sivi kvadrat */    g.setColor(crna);    g.fillOval(180,40,100,100); /*crni krug u sivom kvadratu*/    g.setColor(siva);    g.fillOval(200,60,60,60);  /* sivi krug u crnom krugu */

  }

}      

Java sadrzi metode za crtanje praznih i ispunjenih lukova. Oni su izvedeni iz metoda za crtanje elipsi, ali imaju dva dodatna parametra - pocetak luka i velicinu ugla luka. To su metode drawArc() i fillArc(). Ponasaju se slicno kao drawOval() i fillOval(). Signature:

public abstract void drawArc(int x,                              int y,                              int width,                              int height,                              int startAngle,                              int arcAngle)

public abstract void fillArc(int x,                              int y,                              int width,                              int height,

18

                             int startAngle,                              int arcAngle)

U pravougaonik se upisuje najveci moguci luk. Lokacija luka od 0 stepeni, kao i smer, tj. odgovor da li je luk nacrtan u smeru kazaljke na satu ili suprotnom ne zavisi od platforme. Na primer, poziv     g.fillArc(10,10,100,100,0,90) iscrtava isecak kruga (width=height=100) ciji precnik je 100 tacaka i gornji levi ugao opisanog kvadrata je na poziciji 10,10. Isecak ima formu prve cetvrtine kruga. Uglovi luka se zadaju u celobrojnim vrednostima stepena, a ne u radijanima (koji su argumenti trigonomterijskih funkcija). 0 stepeni bi bilo na vrednosti 3 casovnika,...i uglovi se mere suprotno kretanju kazaljki na satu. Ako se zeli zadavanje uglova u smeru kretanaj kazaljke na satau, onda se koriste negativne vrednosti uglova.

Napisati aplet koji iscrtava sledecu sliku:

import java.applet.*; import java.awt.*;  

public class Lukovi extends Applet {

  public void paint(Graphics g) {         g.fillArc(10,10,100,100, 0, 90);  /* ispunjena prva cetvrtina kruga */         g.drawArc(10,10,100,100,90,180); /* u istom krugu, bez granice druge cetvrtine*/         g.fillArc(10,120,100,100, 90, -60); /*pocetak na vrh i ispod se crta drugi luk, ispunjen kruzni isecak na 60 stepeni udesno */        g.fillArc(120,120,100,50, 270,-210); /*fragment neispunjene elipse; isto kao         g.fillArc(120,120,100,50, 60, 210);*/

   

Programi koji podržavaju GUI (Graphical User Interface) zahtevaju da svaka korisnikova akcija, bio to klik, pritisak tastera,... se smesti u  tzv. red događaja (event queue), prema rodosledu pojave događaja, a potom se oni obrađuju, jedan po jedan u smislu da u petlji programa se čitaju događaji iz reda, a switch naredbom raspodjeljuju odgovarajućim delovima programa koji će ih obraditi..

Yavisno od arhitekture operativnog sistema, može postojatii jedan veliki sistemski red događaja ili  svaka aplikacija može imati sopstveni red događaja, ali se na OS niovu obezbeđuje da događaji stignu do adekvatnih programa.

19

U Java programima svaka virtualna mašina ima jedan glavni AWT red događaja.  

Događaji niskog nivoa (LLE =Low Level) predstavljaju direktnu komunikaciju s korisnikom. Na primer: pritisak na taster, klikanje mišem i slično.  

java.lang.Object         |        +--java.util.EventObject                      |                     +--java.awt.AWTEvent                                     |                                    +--java.awt.event.ComponentEvent                                                  |                                                 +--java.awt.event.InputEvent                           |       |                           |       +--java.awt.event.KeyEvent                           |       |                           |       +--java.awt.event.MouseEvent                           |                           +--java.awt.event.FocusEvent                           |                           +--java.awt.event.ContainerEvent                           |                           +--java.awt.event.WindowEvent  

Uključene su klase:

java.awt.event.ComponentEvent       komponenta premeštena, promenjena veličina komponente

java.awt.event.FocusEvent

         komponenta dobila ili izgubila fokus

java.awt.event.KeyEvent

             pritisnut taster, otpušten taster

java.awt.event.MouseEvent

  taster miša pritisnut, podignut, kliknut, miš pomeren, miš povučen  

java.awt.event.ContainerEvent

    komponenta je dodana kontejneru ili uklonjena iz njega  

20

java.awt.event.WindowEvent

     prozor aktiviran, deaktiviran, otvoren, zatvoren, ikonificiran, deikonificiran  

Događaji visokog nivoa (HLE) ili semantički događaji sadrže u sebi značenje koje je pridruženo komponenti korisničkog interfejsa.

Uključene su klase:

java.awt.event.ActionEvent         izvršena je naredba

java.awt.event.AdjustmentEvent      prilagođena je vrednost (npr. scrollbarom)

java.awt.event.ItemEvent      stanje stavke se promenilo

java.awt.event.TextEvent      vrednost tekstualnog objekta se promenila    

Na primer, kad korisnik klikne mišem na GUI dugme i zatim ga otpusti, GUI dugme će primiti tri odvojena događaja nižeg nivoa, tipa MouseEvent (jedan za pritisak tastera miša-mouse down, drugi za otpuštanje tastera-mouse up, treći za eventualno  nastalo povlačenje miša-mouse drag). GUI dugme će nakon toga obraditi jedan događaj višeg nivoa, tipa ActionEvent.

Ako korisnik klikne mišem na GUI dugme, pomeri miša van GUI dugmeta i onda ga otpusti, GUI dugme će dobiti dva odvojena događaja nižeg nivoa (jedan za mouse down, drugi za mouse drag). Zato će ih ignorisati  i neće učiniti ništa.  

Svaka klasa događaja visokog nivoa je  podklasa od java.awt.AWTEvent.

 java.lang.Object         |        +--java.util.EventObject                    |                    +--java.awt.AWTEvent                                 |                                +--java.awt.event.ActionEvent                                 |                                +--java.awt.event.ItemEvent                                 |

21

                               +--java.awt.event.AdjustmentEvent                                 |                                +--java.awt.event.TextEvent                                 |                                  +--java.awt.event.ComponentEvent                                                  |                                                 +--java.awt.event.InputEvent                           |       |                           |       +--java.awt.event.KeyEvent                           |       |                           |       +--java.awt.event.MouseEvent                           |                           +--java.awt.event.FocusEvent                           |                           +--java.awt.event.ContainerEvent                           |                           +--java.awt.event.WindowEvent  

Za obradu događaja iz reda događaja zadužena je Java runtime. Posebno, ona obezbeđuje da svaki događaj niskog nivoa stigne do odgovarajuće komponente. Java programeri se ne moraju starati o tome kojoj komponenti je koji događaj namenjen, jer OS to  rešava automatski. Specijalno, runtime prosleđuje događaj metodi processEvent() klase java.awt.Component:

protected void processEvent(AWTEvent e)

Metoda processEvent() prepoznaje tip događaja i prosleđuje ga jednoj od pet drugih metoda iz iste klase:

  protected void processComponentEvent(ComponentEvent e)   protected void processFocusEvent(FocusEvent e)   protected void processKeyEvent(KeyEvent e)   protected void processMouseEvent(MouseEvent e)   protected void processMouseMotionEvent(MouseEvent e)  

Svaka od tih metoda pokušava videti da li je neki listener odgovarajućeg tipa registrovan za tu komponentu. Ako jeste, događaj se prosleđuje svakom od registrovanih listenera nepredvidljivim poretkom.

Interno, ove metode koriste objekt tipa java.awt.AWTEventMulticaster kako bi vodile popis registracija listenera uz svaku komponentu.

Različiti EventListeneri Da bi Java programer omogućio odgovaranje na događaje koje dobija komponenta, registruje se (pridružuje komponenti) event listener odgovarajućeg tipa. Event listener je svaki objekt koji

22

implementira  java.util.EventListener. AWT definiše više njegovih podyaglavlja, po jedno za svaki tip događaja. Npr.:

java.awt.event.ComponentListener java.awt.event.ContainerListener java.awt.event.FocusListener java.awt.event.KeyListener java.awt.event.MouseListener java.awt.event.MouseMotionListener java.awt.event.WindowListener java.awt.event.ActionListener java.awt.event.AdjustmentListener java.awt.event.ItemListener java.awt.event.TextListener java.awt.event.AWTEventListener java.awt.event.HierarchyBoundsListener java.awt.event.HierarchyListener java.awt.event.InputMethodListener

Svako od tih interfejsa definiše događaje na koje event listener tog tipa mora biti spreman odgovoriti. Na primer,  MouseListener deklariše sledeće metode:

   public abstract void mouseClicked(MouseEvent e)    public abstract void mousePressed(MouseEvent e)    public abstract void mouseReleased(MouseEvent e)    public abstract void mouseEntered(MouseEvent e)    public abstract void mouseExited(MouseEvent e)  

Kada, na primer, komponenta dobije događaj tipa MouseEvent, njena metoda processMouseEvent() proverava njegov ID da bi ustanovila da li je miš kliknut, pritisnut, otpušten, uveden ili izveden. Tada poziva odgovarajuću metodu u svakom registrirovanom objektu koji implementira MouseListener.  

Primer upotrebe MouseListener  

Primer apleta koji crta crveni krug oko mesta gde korisnik klikne mišem. Kako java.applet.Applet jeste podklasa od java.awt.Component, onda da bi aplet odgovarao na klikanje mišem, uz njega mora biti registrovan odgovarajući MouseListener. U takvim apletima najjednostavnije je da sam applet bude MouseListener. Koordinatni sistem se odnosi na komponentu kojoj je događaj namenjen, ne nužno na ceo aplet.

23

                               OkoKlika.htm

 import java.applet.*; import java.awt.*; import java.awt.event.*;

public class OkoKlika extends Applet implements MouseListener {   /* koordinate pokreta misa */  int x,y;   int brojKlika = 0;

  public void init() {    this.addMouseListener(this);  }

  public void mouseClicked(MouseEvent e) {    x = (int) e.getX();     y = (int) e.getY();    brojKlika++;    this.repaint();   }  

  // Metodi koje Java programeri moraju da implementiraju, ali koje ne moraju da urade bilo kakve korisne akcije, //te je telo prazno   public void mousePressed(MouseEvent e) {}   public void mouseReleased(MouseEvent e) {}   public void mouseEntered(MouseEvent e) {}   public void mouseExited(MouseEvent e) {}

  // iscrtavanje tackica   public void paint(Graphics g) {     g.setColor(Color.red);     if ( brojKlika > 0 )   g.fillOval(x, y, 28, 28);   } }    

<APPLET CODE="OkoKlika.class"  WIDTH=200 HEIGHT=200>  </APPLET>          

Primer apleta koji crta do 20 tacaka kada korisnik klikne mišem. Aplert radi sa dogadjajem mouseDown tako da inicajlnp prazan ekran miruje i čeka akciju

24

korisnika. Svaki klik korisnik na prozor apleta crta plavu tačku.  

                               MisTacke.htm   

import java.awt.Graphics; import java.awt.Color; import java.awt.Event;

public class MisTacke extends java.applet.Applet {     final int MAXSPOTS = 20;     int xtacke[] = new int[MAXSPOTS];     int ytacke[] = new int[MAXSPOTS];     int i = 0;    /* brojacka promenljiva, red. br. tekuce tacke */

    public void init() {         setBackground(Color.white);     }

    public boolean mouseDown(Event evt, int x, int y) {         if (i < MAXSPOTS) {             dodajTacku(x,y);             return true;         }         else {             System.out.println("Mnogo tackica.");             return false;         }     }

    void dodajTacku(int x,int y) {         xtacke[i] = x;         ytacke[i] = y;         i++;         repaint();     }

    public void paint(Graphics g) {         g.setColor(Color.blue);         for (int k = 0; k < i; k++) {             g.fillOval(xtacke[k] - 10, ytacke[k] - 10, 20, 20);         }     } }

25

     

<APPLET CODE="MisTacke.class"  WIDTH=250 HEIGHT=250>  </APPLET>    

Primer apleta koji crta prava linije u prozoru tako da se nalaze izmedju do  10 tacaka selektovanih kada korisnik klikne mišem. Aplert radi sa dogadjajem mouseDown kao u prethodnom primerutako da inicajlno prazan ekran miruje i čeka akciju korisnika. Ali, ya rayliku od prethodnog apleta, aplet Linije ne cuva podatke pojedinih celobrojnih koordinata tacki, vec cuva podatke o objektima tacaka (Point). Za rad sa tačkama koristi se klasa Point (java.awt.Point).  

                               Linije.htm

import java.awt.Graphics; import java.awt.Color; import java.awt.Event; import java.awt.Point;

public class Linije extends java.applet.Applet {     final int MAXLinije = 10;     Point startneTacke[] = new Point[MAXLinije]; // start Tacke     Point zavrsneTacke[] = new Point[MAXLinije];    // kraj Tacke     Point polazna;    // start tekuce linije     Point tekTacke; // tekuci kraj linije     int ukupno = 0; // broj linija

    public void init() {         setBackground(Color.white);     }

    public boolean mouseDown(Event evt, int x, int y) {         if (ukupno < MAXLinije) {             polazna = new Point(x,y);             return true;         }         else  {             System.out.println("Previse linija.");             return false;         }     }

26

    public boolean mouseUp(Event evt, int x, int y) {         if (ukupno < MAXLinije) {              dodajLiniju(x,y);              return true;         }         else return false;     }

    public boolean mouseDrag(Event evt, int x, int y) {         if (ukupno < MAXLinije) {             tekTacke = new Point(x,y);             repaint();             return true;         }         else return false;     }

    void dodajLiniju(int x,int y) {         startneTacke[ukupno] = polazna;         zavrsneTacke[ukupno] = new Point(x,y);         ukupno++;         tekTacke = null;         polazna = null;         repaint();     }

    public void paint(Graphics g) {         // crta postojece Linije         for (int i = 0; i < ukupno; i++) {             g.drawLine(startneTacke[i].x, startneTacke[i].y,                  zavrsneTacke[i].x, zavrsneTacke[i].y);         }

        // crta tekucu liniju         g.setColor(Color.blue);         if (tekTacke != null)             g.drawLine(polazna.x,polazna.y,                 tekTacke.x,tekTacke.y);     } }    

Događaji vezani uz tastaturu (Key Events)

27

Događaj  java.awt.event.KeyEvent šalje se komponenti ako korisnik pritisne taster dok komponenta ima fokus. Ti su događaji predstavljeni po jednom celobrojnom konstantom:  

KeyEvent.KEY_PRESSED  Taster je pritisnut

KeyEvent.KEY_RELEASED  Taster je otpušten

KeyEvent.KEY_TYPED  Taster je pritisnut i zatim otpušten  

Uz neki KeyEvent je u većini slučaja potrebno saznati i koji taster je pritisnut, što se saznaje pomoću metode getKeyChar():

public char getKeyChar() Ona  vraća Unicode znak koji odgovara pritisnutom tasteru.    

Događaji kao KEY_PRESSED ili KEY_RELEASED ne nose samo znak. Oni takođe imaju i kôd tastera. (Za razliku od njih, događaji KEY_TYPED nemaju kôd, odnosno, kôd im je nedefinisan). Ako za neki KeyEvent trebate saznati koji taster je pritisnut, a ne koji je znak upisan,  koristan je  metod getKeyCode():

public int getKeyCode()

Moguće je izvršiti i  konverziju u lokalizovani string kao na primer "END", "F4" ili "Q" pomoću statičke metode KeyEvent.getKeyText():

public static String getKeyText(int keyCode)

Po pravilu na događaje vezanih za tastaturu odgovara se u samoj komponenti, tako da se uz nju registriruje neki KeyListener.  Interfejs KeyListener deklariše sledeće metode, po jednu za svaki tip KeyEventa.

  public abstract void keyTyped(KeyEvent e)   public abstract void keyPressed(KeyEvent e)   public abstract void keyReleased(KeyEvent e)

28

1.12Kôdovi tastera

Nekonzistentnost tastatura je je jedan od problema s kojima se multiplatformski programski jezik mora na suočiti. Nisu sve tastature konzistene, jer npr.  Mac ima tastere za naredbe i opcije, PC ima Alt tasere. Neki imaju numeričku tastaturu, neki ne. Neki imaju Start taser, neki ne. Emacs očekuje Meta taster koja retko postoji kao zaseban,  već kao Escape taster...

Klasa Java.awt.event.KeyEvent definiše nešto više od stotinu virtualnih kôdova za tastere koji se mapiraju na različite, uvek prisutne, tastere. KeyEvent.VK_0 do KeyEvent.VK_9 su efekti znakovnih konstanti   '0' do '9' (ASCII: 0x30 - 0x39)

KeyEvent.VK_0 KeyEvent.VK_1 KeyEvent.VK_2 KeyEvent.VK_3 KeyEvent.VK_4 KeyEvent.VK_5 KeyEvent.VK_6 KeyEvent.VK_7 KeyEvent.VK_8 KeyEvent.VK_9 KeyEvent.VK_A do KeyEvent.VK_Z su isti kao ASCII 'A' do 'Z'; dakle, postoji  KeyEvent.VK_A, KeyEvent.VK_B, KeyEvent.VK_C, KeyEvent.VK_D, KeyEvent.VK_E, KeyEvent.VK_F itd.  

Različiti tasteri i njihovi kôdovi

Tasteri kôdovi od značaja:  

KeyEvent.VK_ACCEPT KeyEvent.VK_ADD KeyEvent.VK_ALT KeyEvent.VK_BACK_QUOTE KeyEvent.VK_BACK_SLASH KeyEvent.VK_BACK_SPACE KeyEvent.VK_CANCEL

29

KeyEvent.VK_CAPS_LOCK KeyEvent.VK_CLEAR KeyEvent.VK_CLOSE_BRACKET KeyEvent.VK_COMMA KeyEvent.VK_CONTROL KeyEvent.VK_CONVERT KeyEvent.VK_DECIMAL KeyEvent.VK_DELETE KeyEvent.VK_DIVIDE KeyEvent.VK_DOWN KeyEvent.VK_END KeyEvent.VK_ENTER KeyEvent.VK_EQUALS KeyEvent.VK_ESCAPE KeyEvent.VK_F1 KeyEvent.VK_F2 KeyEvent.VK_F3

KeyEvent.VK_F4 KeyEvent.VK_F5 KeyEvent.VK_F6 KeyEvent.VK_F7 KeyEvent.VK_F8 KeyEvent.VK_F9 KeyEvent.VK_F10 KeyEvent.VK_F11 KeyEvent.VK_F12 KeyEvent.VK_FINAL KeyEvent.VK_HELP KeyEvent.VK_HOME KeyEvent.VK_INSERT KeyEvent.VK_KANA KeyEvent.VK_KANJI KeyEvent.VK_LEFT KeyEvent.VK_META KeyEvent.VK_MODECHANGE KeyEvent.VK_MULTIPLY KeyEvent.VK_NONCONVERT KeyEvent.VK_NUM_LOCK KeyEvent.VK_NUMPAD0 KeyEvent.VK_NUMPAD1 KeyEvent.VK_NUMPAD2 KeyEvent.VK_NUMPAD3

KeyEvent.VK_NUMPAD4 KeyEvent.VK_NUMPAD5

30

KeyEvent.VK_NUMPAD6 KeyEvent.VK_NUMPAD7 KeyEvent.VK_NUMPAD8 KeyEvent.VK_NUMPAD9 KeyEvent.VK_OPEN_BRACKET KeyEvent.VK_PAGE_DOWN KeyEvent.VK_PAGE_UP KeyEvent.VK_PAUSE KeyEvent.VK_PERIOD KeyEvent.VK_PRINTSCREEN KeyEvent.VK_QUOTE KeyEvent.VK_RIGHT KeyEvent.VK_SCROLL_LOCK KeyEvent.VK_SEMICOLON KeyEvent.VK_SEPARATER KeyEvent.VK_SHIFT KeyEvent.VK_SLASH KeyEvent.VK_SPACE KeyEvent.VK_SUBTRACT KeyEvent.VK_TAB KeyEvent.VK_UNDEFINED KeyEvent.VK_UP    

Modifikatori

Obe klase, KeyEvent i MouseEvent su podklase od java.awt.event.InputEvent čiji glavni zadatak je testiranje dodatnih slova u smislu da li je taster ALT pritisnut zajedno s nekim drugim, ili SHIFT taster istovremeno s mišem i slično.

Sljedeće četiri metode testiraju da li je ili nije pritisnut određen taster u trenutku kad je događaj poslan.   public boolean isShiftDown()   public boolean isControlDown()   public boolean isMetaDown()   public boolean isAltDown() Sve se one mogu pozivati i uz MouseEvent i uz KeyEvent objekte.

Postoji i metod getWhen() koji vraća vreme kad je događaj nastao. Vreme se zadaje u milisekundama od ponoći 1.1.1970. UTC.

public long getWhen()

31

Klase java.util.Date i java.util.Calendar imaju metode pomoću kojih programer može izvršiti konverziju u tradicinalan način zapisivanja datum i vremena. No najčešće će programera zapravo zanimati samo vremenska razlika između dva događaja.

Primer apleta koji u centru prozora prikazuje karakter koji je otkucao korisnik. Karakter se može po ekranu koristeći kursorske tastere za levo. desno, naviše, nadole. Prikazani karakter menja se kucanjem sledećeg karaktera.

                                  Tasteri.htm

import java.awt.Graphics; import java.awt.Event; import java.awt.Font; import java.awt.Color;

public class Tasteri extends java.applet.Applet {

    char tekTaster;     int xTastera;     int yTastera;

    public void init() {         xTastera = (size().width / 2) -8;  // podrazumevane         yTastera = (size().height / 2) -16;

        setBackground(Color.white);         setFont(new Font("Helvetica",Font.BOLD,24));         requestFocus();     }

    public boolean keyDown(Event evt, int taster) {         switch (taster) {         case Event.DOWN:             yTastera += 5;             break;         case Event.UP:             yTastera -= 5;             break;         case Event.LEFT:             xTastera -= 5;             break;         case Event.RIGHT:             xTastera += 5;             break;         default:

32

            tekTaster = (char)taster;         }

        repaint();         return true;     }

    public void paint(Graphics g) {         if (tekTaster != 0) {             g.drawString(String.valueOf(tekTaster), xTastera,yTastera);         }     } }  

1.13Modifikatori uz taster miša

Događaji tipa InputEvent čuvaju se kao int vrednosti. Svaki bit u takvom broju je flag koji odgovara određenom modifikatoru. Vrednosti tih flagova su zadate pomoću int konstanti koje su public final static unutar InputEvent klase:

InputEvent.SHIFT_MASK InputEvent.CTRL_MASK InputEvent.META_MASK InputEvent.ALT_MASK InputEvent.ALT_GRAPH_MASK InputEvent.BUTTON1_MASK InputEvent.BUTTON2_MASK InputEvent.BUTTON3_MASK

Moguće ih je saznati pomoću metode getModifiers():

public int getModifiers()

Koristite bitovski operator & kad želite testirati da li je neki flag podignut. Npr,

if (e.getModifiers() & InputEvent.BUTTON2_MASK != 0) {  System.out.println("Pritisnut 2. taster");}

33

1.14Događaji vezani uz fokus

U svakom trenutku točno jedna komponenta u apletu ima fokus, odnosno mogućnost primanja ulaza s tastature ili miša. Događaji niskog nivoa će u tom trenutku biti usmereni prema toj komponenti.

Fokus je moguće podesiti na više načina. Npr, kad korisnik pritisne taster Tab, fokus će  biti premešten s dotadašnje komponente na sledeću. Ako korisnik pritisne Shift-Tab, fokus će se vratiti na prethodnu komponentu. Ako korisnik izabere komponentu mišem, ona će dobiti fokus.

Bez obzira na koji način komponenta dobije ili izgubi fokus, ona uzrokuje pojavu događaja tipa java.awt.event.FocusEvent. Promena fokusa može biti stalna ili privremena. Stalna promena nastaje kad je fokus direktno premešten s jedne komponente na drugu, bilo pozivanjem komponentine metode requestFocus() ili akcijom korisnika, npr. pomoću Tab tastera. Privremena promena fokusa nastaje kao indirektni rezultat druge operacije, na primer deaktiviranja prozora. U tom slučaju početno stanje fokusa će biti automatski restaurirano kad se operacija završi ili prozor opet aktivira.

Metoda isTemporary() vraća true ako je promena fokusa privremena, a false ako je stalna:

public boolean isTemporary()

Na događaje vezane uz promenu fokusa programer može odgovoriti ako uz komponentu instalira  java.awt.event.FocusListener. Interfejs deklariše dva metoda:

  public abstract void focusGained(FocusEvent e)   public abstract void focusLost(FocusEvent e)

1.15Događaji vezani uz komponentu (Component Events)

Klasa java.awt.event.ComponentEvent je nadklasa svim klasama događaja koji su do sad pominjani. Ona se odnosi i na nekoliko sopstvenih događaja koji omogućuju reaakciju nakon što se komponenta prikaže, sakrije, premesti  ili joj se promeni veličina. Oni su predstavljeni konstantama:

 ComponentEvent.COMPONENT_MOVED  ComponentEvent.COMPONENT_RESIZED  ComponentEvent.COMPONENT_SHOWN  ComponentEvent.COMPONENT_HIDDEN

34

Kao i obično, na te događaje programer može odgovarati ako uz svoju komponentu registruje odgovarajući objekt iz klase koja implementira java.awt.event.ComponentListener  u kom su  deklarisane četiri metode:

   public abstract void componentResized(ComponentEvent e)    public abstract void componentMoved(ComponentEvent e)    public abstract void componentShown(ComponentEvent e)    public abstract void componentHidden(ComponentEvent e) Klasa java.awt.event.ComponentEvent nema neke sopstvene naročito korisne metode, ali programer može koristiti metode iz klase java.awt.Component kad želite ustanoviti lokaciju na koju je komponenta pomerena ili na koju veličinu je preoblikovana.  

--------------------------------------------------------------------------------

Adapteri Adapteri su klase koje implementiraju sve metode interfejsa tako da sve deklarisane metode interfejsa prekriju metodama koje ne čine ništa. AWT osigurava više adapterskih klasa za različite vrste EventListenera. To su:

ComponentAdapter ContainerAdapter FocusAdapter KeyAdapter MouseAdapter MouseMotionAdapter WindowAdapter Na primer, interface MouseListener deklariše sledeće metode:

   public abstract void mouseClicked(MouseEvent e)  public abstract void mousePressed(MouseEvent e)  public abstract void mouseReleased(MouseEvent e)  public abstract void mouseEntered(MouseEvent e)  public abstract void mouseExited(MouseEvent e)

Zato odgovarajući adapter, java.awt.event.MouseAdapter izgleda ovako:

 package java.awt.event; import java.awt.*; import java.awt.event.*;  public class MouseAdapter implements MouseListener  {

     public void mouseClicked(MouseEvent e) {}      public void mousePressed(MouseEvent e) {}      public void mouseReleased(MouseEvent e) {}

35

     public void mouseEntered(MouseEvent e) {}      public void mouseExited(MouseEvent e) {}

}

Ako sada napravite podklasu klase MouseAdapter umesto da direktno implementirate MouseListener, izbeći će se pisanje metoda koje zapravo i ne trebaju. Pregaziće se jedino one metode koje stvarno želite implementirati. Adapteri su svojevrsno pojednostavnjenje posla prilikom implementacije interface-a. Mogu se koristiti ako želi programer, ali i ne moraju.    

Primer upotrebe adaptera

   Adapter za miša koji proizvodi signal zvona kad korisnik klikne mišem.

 import java.applet.Applet;

public class MisZvono extends Applet {    

  public void init() {

    MouseBeeper mb = new MouseBeeper();

    this.addMouseListener(mb);

  }

}    

 import java.awt.*; import java.awt.event.*; public class MouseBeeper extends MouseAdapter {   public void mouseClicked(MouseEvent e)

     {    Toolkit.getDefaultToolkit().beep();  } }  

<APPLET CODE="MisZvono.class"  WIDTH=200 HEIGHT=200>

</APPLET>

36

 Kad MouseBeeper ne bi bio podklasa od MouseAdapter morao bi izgledati ovako:

 import java.awt.*; import java.awt.event.*; public class MouseBeeper implements MouseListener  {        public void mouseClicked(MouseEvent e)          {    Toolkit.getDefaultToolkit().beep();  }       public void mousePressed(MouseEvent e) {}       public void mouseReleased(MouseEvent e) {}       public void mouseEntered(MouseEvent e) {}      public void mouseExited(MouseEvent e) {}

}

37

2 Kontrola razmeštaja komponenti

Kontrolu nad razmeštajem pozicija komponenti koje se dodaju  omogućuje  skup klasa koji se nazivaju menadžeri postavke. java.awt.LayoutManager sadrži metode koje organizuju komponente interfejsa u kontejnere. Budući da se  unapred ne zna veličina ni oblik površine s kojom se radi, kontrola će biti relativna, dakle uglavnom se odlučuje o tome treba li neka komponenta biti iznad ili ispod druge, s levim ili desnim poravnanjem, ali se po pravilu  ne određuje da li će se  komponenta pojaviti  u nekoj specifičnoj tački.    

2.1.1 Ručno pozicioniranje komponenti

AWT je konstruisan tako da GUI programa može da funkcioniše podjedanko dobro na različitim platformama i sa različitim rezolucijama ekrana, fontovima, veličinama ekrana i slično,...Oslanjanje na koordinate u pikselima ima za posledicu da program izgleda onako kako ste želeli na jednoj platformi, dok na drugim platformama može biti neupotrebljiv usled preklapanja komponenti,... Menadžeri postavke rade dinamičko smeštanje komponenti na ekranu i tako zaobilaze te probleme.  

Narvno, komponente je moguće postaviti na tačno određenu poziciju na ekranu, koristeći koordinate u pikselima, u odnosu na apletov panel. To, međutim, ima više nedostataka:  

Sve instance Vašeg appleta neće imati panel jednake veličine. Veličinu možete kontrolisati samo ako će se aplet pojavljivati jedino na vašim web stranicama.  Korisnici mogu menjati veličinu slobodnim prozorima u hodu. Ako koristite layout manager, sve će komponente biti automatski prilagođene novoj veličini prozora. Bez toga vrlo je teško postići takvo ponašanje. Komponente će na različitim platformama zauzimati različite količine prostora. Ručno pozicioniranje će imati smisla u aplikacijama koje su namenjene izvršavanju na jednoj određenoj platformi. Apleti nisu pogodni za to. Ručno pozicioniranje komponenti traži mnogo posla, pogotovo ako nemate na raspolaganju neki alat koji će automatizirati taj proces. Razmeštaj GridBagLayout u kombinaciji sa ugnježdenim panelima dovoljan je za sve efekte koje biste inače mogli postići ručnim pozicioniranjem. Ako ipak želite ručno pozicionirati komponente, onda prvo opozovite layout manager naredbom:

 setLayout(null); Nakon toga zadajte poziciju i veličinu za svaku komponentu unutar paint() metode (eksplicitno je rečeno da se to inače ne radi!), tako da pozovete metode setLocation() and setSize():

 public void setLocation(int x, int y) public void setSize(int width, int height)

38

Ovde su x i y koordinate levog gornjeg ugla kutije koja omeđuje  komponentu, a width i height su njena širina i visina u pikselima.

Sledeći aplet staviće dugme veličine 30 x 40 piksela (tj. njegov levi gornji ugao) u tačku (25, 50):

import java.applet.*; import java.awt.*;

public class RucniRazmestaj extends Applet {   private boolean postavljen = false;  private Button Dugme;

  public void init() {     this.setLayout(null);    this.Dugme = new Button("OK");    this.add(this.Dugme);  }

   public void paint(Graphics g) {     if (!this.postavljen) {        this.Dugme.setLocation(25, 50);        this.Dugme.setSize(30, 40);        this.postavljen = true;     }   }

}

<APPLET CODE="RucniRazmestaj.class"  WIDTH=100 HEIGHT=100> </APPLET>    

   Primer   

2.1.2 Implementacije LayoutManagera

Interface java.awt.LayoutManager implementiran je u više različitih klasa, kao što su:

java.awt.FlowLayout java.awt.BorderLayout java.awt.CardLayout

39

java.awt.GridLayout java.awt.GridBagLayout  

Appleti ili kontejneri mogu koristiti ove i druge layout managere da bi odlučili gde će postaviti komponente koje u njih programer dodaje.  

Klasa java.awt.FlowLayout raspoređuje komponente s leva na desno dok ima prostora, a tada nastavlja na isti način odozgo na dole. Svaka komponenta u FlowLayout razmeštaju dobija upravo onoliko prostora koliko joj minimalno treba i ništa više. Takav je razmeštaj koristan za raspoređivanje GUI dugmića, ali za mnoge druge stvari nije. On je pretpostavljeni (default) razmeštaj za aplete i panele (posebne kontejnere).

Klasa java.awt.BorderLayout organizuje aplet u sekcije prema stranama sveta: North, South, East, West i Center. North, South, East i West su pravougaonici na rubovima apleta. Oni se kontinuirano šire prema veličini komponenata u njima. Center je ono što preostane u središtu.

Klasa java.awt.CardLayout deli aplet na površine u obliku karti gde svaka ima sopstveni razmeštaj. U svakom trenutku samo se jedna karta pojavljuje na ekranu. Korisnik može prebacivati izgled ekrana s jedne na drugu kartu, a svaka prikazuje različite skupove komponenti. Obično se to upoređuje sa HyperCardom na Macu ili Toolbookom na Windowsima. U Javi  se to može koristiti kao serija maski za unos podataka ako sva polja ne mogu stati na ekran.

Klasa java.awt.GridLayout deli aplet na određeni broj redova i kolona te tako formira mrežu ćelija kao matricu. Kako se koja komponenta dodaje, ona se smešta u sledeću slobodnu ćeliju, počevši od levog ugla prema desno i prema dole. Svaka komponenta se podešava po veličini tako da pristaje u ćeliju. Takav razmeštaj će neke komponente nepotrebno stisnuti, a neke razvući, ali je veoma pogodan za razmeštanje panela.

Klasa java.awt.GridBagLayout daje najprecizniji od svih AWT razmeštaja. Razmeštaj je kao i GridLayout, ali komponente ne moraju biti iste veličine. Svaka komponenta može zauzeti jednu ili više ćelija. Štaviše, komponente nisu nužno smeštene u ćelije počevši od gornjeg levog ugla niti se moraju dodavati prema desno i prema dole.

U jednostavnim apletima sa samo nekoliko komponenti biće dovoljan jedan razmeštaj. U komplikovanijima, međutim, često se aplet deli na panele koji se raspoređuju prema nekom razmeštaju, a onda svaki panel snabdeti sopstvenim layout managerom za raspoređivanje komponenti unutar njega.  

40

2.1.3 Razmeštaj tipa FlowLayout

Klasa java.awt.FlowLayout raspoređuje komponente s leva na desno dok ima prostora, a tada nastavlja isti postupak odozgo naniže. Svaka komponenta dobija upravo  mesta koliko joj treba i ništa više. Ovaj je tip razmeštaja najkorisniji za raspoređivanje dugmića.

FlowLayout je pretpostavljeni (default) razmeštaj za java.awt.Panel koji je nadklasa od java.applet.Applet, te se ne mora učiniti ništa posebno kako bi se FlowLayout kreirao unutar apleta. Međutim, ako ga želite koristiti unutar prozora, java.awt.Window, biće potrebni odgovarajući konstruktori.

Razmeštaji imaju konstruktore kao i ostale klase. Jedan od konstruktora za FlowLayout je:

public FlowLayout()

Dakle, za kreiranje novog objekta tipa FlowLayout piše se:

FlowLayout fl; fl = new FlowLayout();

Kao i obično, to se može kompaktnije zapisati: FlowLayout fl = new FlowLayout();

Apletu ćete reći koju specifičnu instancu klase LayoutManager želite koristiti, tako da taj objekt navedete u apletovoj metodi setLayout(). Ovu metodu klasa java.applet.Applet nasleđuje, kao i mnoge druge, iz klase java.awt.Container.

this.setLayout(fl);

Metoda setLayout() se uglavnom poziva u init() metodi. Uobičajeno je kreirati primerak razmeštaja direktno unutar poziva metode setLayout() ovako:

this.setLayout(new FlowLayout());  

2.1.4 Podešavanje poravnanja za FlowLayout

Poravnanje za neki FlowLayout se zadaje pomoću odgovarajućeg konstruktora. Komponente su u apletu po pretpostavci centrirane, a mogu da budu i levo ili desno pozicionirane, jer postoje konstante FlowLayout.LEFT, FlowLayout.RIGHT ili FlowLayout.CENTER koje se navode prilikom pozivanja konstruktora, npr.

41

 this.setLayout(new FlowLayout(FlowLayout.LEFT)); this.setLayout(new FlowLayout(FlowLayout.RIGHT)); this.setLayout(new FlowLayout(FlowLayout.CENTER));

Primer u kojem se poravnanje zadaje pomoću parametra oznake <APPLET>.

 import java.applet.Applet; import java.awt.Button; import java.awt.FlowLayout;

 public class TapeDeckAlign extends Applet {

   public void init() {     FlowLayout f;     String align = getParameter("align");

    if (align == null) f = new FlowLayout(FlowLayout.CENTER);     else if (align.equalsIgnoreCase("left"))   f = new FlowLayout(FlowLayout.LEFT);     else if (align.equalsIgnoreCase("right"))       f = new FlowLayout(FlowLayout.RIGHT);     else  f = new FlowLayout(FlowLayout.CENTER);

    setLayout(f);     add( new Button("Play"));     add( new Button("Rewind"));     add( new Button("Fast Forward"));     add( new Button("Pause"));     add( new Button("Stop"));    } }

 <APPLET CODE="TapeDeckAlign.class" WIDTH=200 HEIGHT=100><param name="align" value="left"></APPLET>  

            Primer 

  S parametrom value="center", odnosno value="right" dobili bismo centrirani i desno pozicionirani razmeštaj.  

42

2.1.5 Razdvajanje komponenti za FlowLayout

Većina LayoutManagera omogućuje kontrolu nad minimalnim vertikalnim i horizontalnim prostorom koji razdvaja komponente. Za FlowLayout zadaje se željeni prostor u pikselima, putem odgovarajućih argumenata u konstruktoru:

public FlowLayout(int alignment, int hspace, int vspace);

Na primer, da biste napravili FlowLayout sa deset piksela horizontalnog i dvadeset piksela vertikalnog razmaka, sa levim poravnanjem, koristili biste sledeći konstruktor: FlowLayout fl =  new FlowLayout(FlowLayout.LEFT, 20, 10);

Primer apleta koji tako raspoređuje buttone nalik onima za VCR:

 import java.applet.*;  import java.awt.*; public class SpaceTapeDeck extends Applet {   public void init() {      this.setLayout( new FlowLayout(FlowLayout.LEFT, 20, 10));     this.add( new Button("Play"));    this.add( new Button("Rewind"));    this.add( new Button("Fast Forward"));    this.add( new Button("Pause"));    this.add( new Button("Stop"));      } }

<APPLET CODE="VCR2.class" WIDTH=200 HEIGHT=200>  </APPLET>

2.1.6 Razmeštaj tipa BorderLayout

Klasa java.awt.BorderLayout smešta objekte na NORTH, SOUTH, EAST, WEST ili CENTER unutar apleta. Da biste kreirali novi objekt tipa BorderLayout, pozovite, slično kao i za FlowLayout unutar metode init() metodu setLayout() ovako:

 this.setLayout(new BorderLayout());

43

U ovom tipu razmeštaja nema centriranja ni levog ili desnog poravnavanja, no možete dodati horizontalne i vertikalne razmake među komponentama. Na primer, za horizontalni razmak od 5 piksela i vertikalni od 10 piksela, stavili bismo:

 this.setLayout(new BorderLayout(5, 10));

Kad želite dodati komponentu na određenu stranu, možete to učiniti na primer ovako:  this.add(new Button("Start"), BorderLayout.SOUTH);

Kao što se iz sledećeg primera može videti, severna i južna sekcija protežu se preko apleta s leva na desno. Istočna i zapadna se protežu od dna severne do vrha južne sekcije. Ove četiri komponente biće velike onoliko koliko je potrebno da bi u njih stale komponente koje im dodeljujete. Ono što ostane, biće za centralnu sekciju. Tačne veličine su nepredvidljive. Kao i tačan način pakiranja komponenti unutar sekcija.  

import java.awt.*;

public class BorderLayout1 extends java.applet.Applet {     BorderLayout b = new BorderLayout();     Button north = new Button("North");     Button south = new Button("South");     Button east = new Button("East");     Button west = new Button("West");     Button center = new Button("Center");

    public void init() {         setLayout(b);         add("North", north);         add("South", south);         add("East", east);         add("West", west);         add("Center", center);     } }    

<APPLET CODE="BorderLayout1.class"  WIDTH=200 HEIGHT=100> </APPLET>      

             Primer   

44

import java.applet.*; import java.awt.*;    public class BorderLayout2 extends Applet {         public void init() {            this.setLayout(new BorderLayout(20, 10));           this.add(new Button("North"),  BorderLayout.NORTH);           this.add(new Button("South"),  BorderLayout.SOUTH);           this.add(new Button("East"),   BorderLayout.EAST);           this.add(new Button("West"),   BorderLayout.WEST);          this.add(new Button("Center"), BorderLayout.CENTER);          } }

<APPLET CODE="BorderLayout2.class"  WIDTH=200 HEIGHT=100> </APPLET>  

   

2.1.7 Razmeštaj tipa CardLayout

Razmeštaj koji implementira klasa java.awt.CardLayout pretvara aplet u snop karata, od kojih svaka potencijalno ima svoj LayoutManager. U svakom trenutku na ekranu je vidljiva samo jedna karta. Možete prelaziti s jedne karte na drugu, dovodeći tako svaki put na ekran drugi skup komponenti. Postoji sličnost sa HyperCardom na Mac-u ili Toolbookom na Windowsima. U Javi se takav razmeštaj može koristiti kao niz ekrana za unos ako svi podaci ne stanu na jedan. Ako je potrebno prikazati više podataka, onda se može napraviti  slide show.

Na primer, pogledajte sledeći aplet, CardTest, jeste jedan od Sunovih standardnih demo appleta. On koristi CardLayout za prebacivanje s jednog razmeštaja na drugi, pri čemu se na različite načine raspoređuju isti dugmici:

<APPLET CODE="CardTest.class"  WIDTH=400 HEIGHT=200>  </APPLET>

        Demo primer

/*  * @(#)CardTest.java  *  * Copyright 2002 Sun Microsystems, Inc. All rights reserved.  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.  */

45

import java.awt.*; import java.awt.event.*; import java.applet.Applet;

class CardPanel extends Panel {     ActionListener listener;

    Panel create(LayoutManager layout) {  Button b = null;  Panel p = new Panel();

 p.setLayout(layout);

 b = new Button("one");  b.addActionListener(listener);  p.add("North", b);

 b = new Button("two");  b.addActionListener(listener);  p.add("West", b);

 b = new Button("three");  b.addActionListener(listener);  p.add("South", b);

 b = new Button("four");  b.addActionListener(listener);  p.add("East", b);

 b = new Button("five");  b.addActionListener(listener);  p.add("Center", b);

 b = new Button("six");  b.addActionListener(listener);  p.add("Center", b);

 return p;     }

    CardPanel(ActionListener actionListener) {  listener = actionListener;  setLayout(new CardLayout());  add("one", create(new FlowLayout()));  add("two", create(new BorderLayout()));  add("three", create(new GridLayout(2, 2)));

46

 add("four", create(new BorderLayout(10, 10)));  add("five", create(new FlowLayout(FlowLayout.LEFT, 10, 10)));  add("six", create(new GridLayout(2, 2, 10, 10)));     }

    public Dimension getPreferredSize() {  return new Dimension(200, 100);     } }

public class CardTest extends Applet         implements ActionListener,      ItemListener {     CardPanel cards;

    public CardTest() {  setLayout(new BorderLayout());  add("Center", cards = new CardPanel(this));  Panel p = new Panel();  p.setLayout(new FlowLayout());  add("South", p);

 Button b = new Button("first");  b.addActionListener(this);  p.add(b);

 b = new Button("next");  b.addActionListener(this);  p.add(b);

 b = new Button("previous");  b.addActionListener(this);  p.add(b);

 b = new Button("last");  b.addActionListener(this);  p.add(b);

 Choice c = new Choice();  c.addItem("one");  c.addItem("two");  c.addItem("three");  c.addItem("four");  c.addItem("five");  c.addItem("six");  c.addItemListener(this);

47

 p.add(c);     }

    public void itemStateChanged(ItemEvent e) {  ((CardLayout)cards.getLayout()).show(cards,                                       (String)(e.getItem()));     }

    public void actionPerformed(ActionEvent e) {  String arg = e.getActionCommand();

 if ("first".equals(arg)) {      ((CardLayout)cards.getLayout()).first(cards);  } else if ("next".equals(arg)) {      ((CardLayout)cards.getLayout()).next(cards);  } else if ("previous".equals(arg)) {      ((CardLayout)cards.getLayout()).previous(cards);  } else if ("last".equals(arg)) {      ((CardLayout)cards.getLayout()).last(cards);  } else {      ((CardLayout)cards.getLayout()).show(cards,(String)arg);  }     }

    public static void main(String args[]) {  Frame f = new Frame("CardTest");  CardTest cardTest = new CardTest();  cardTest.init();  cardTest.start();

 f.add("Center", cardTest);  f.setSize(300, 300);  f.show();     }

    public String getAppletInfo() {         return "Demonstrates the different types of layout managers.";     } }  

2.1.8 Upotreba CardLayout razmeštaja

Ovaj razmeštaj se kreira pomoću konstruktora CardLayout():      this.setLayout(new CardLayout());

48

Postoji još jedan konstruktor kojim se može odrediti razmak među komponentama:     this.setLayout(new CardLayout(3, 4));

Primer: Neka komponente budu razmaknute 3 pixela horizontalno i 4 pixela vertikalno. Svaka karta ima ime. Nova karta se kreira kad dodate komponentu karti koja do tada nije uvedena. Komponente dodajete tako da navedete ime karte i instancu komponente u metodi add():

this.setLayout(new CardLayout());

this.add("Sladoled", new Label("Volite i sladoled?")); this.add("Sladoled", new Button("OK"));

this.add("Placanje", new Label("Nacin placanja?")); this.add("Placanje", new Button("OK"));

this.add("Address", new Label("Nacin preuzimanja paketa")); this.add("Address", new Button("Narucite"));  

Često se karte imenuju po brojevima:

 this.setLayout(new CardLayout());

this.add("1", new Label("Prva karta")); this.add("2", new Label("Druga karta")); this.add("3", new Label("Treca karta")); this.add("4", new Label("Cetvrta karta")); this.add("5", new Label("Peta karta")); this.add("6", new Label("Sesta karta"));

Interno se popis karata i njihovih imena čuva u objekta tipa java.util.Hashtable, a  to znači da redosleda karata nije ugražen ili garantovan, već o  tome se stara programer.  

2.1.9 Promena karata

Po pravilu svakoj karti se dodaje panel koji ima sopstveni LayoutManager. Svaka karta mora biti snabdevena smernicama za navigaciju među kartama. Ali,  AWT nema ugrađen takav alat. Kako jednu komponentu možete dodati na više od jedne karte, to svojstvo je korisno, na primer, za kreiranje Choice selektora sa imenima svih karata kao pomoći pri navigaciji.

Narednih pet metoda klase java.awt.CardLayout omogućuje promenu aktivne karte. U svim slučajevima treba specificirati kontejner unutar kog se prelazi s karte na kartu. To može biti aplet, prozor ili panel koji je uređen u skladu s tim razmeštajem.

49

  public void first(Container parent)   public void next(Container parent)   public void previous(Container parent)  public void last(Container parent)  public void show(Container parent, String name)  

2.1.10Razmeštaj tipa GridLayout

Klasa java.awt.GridLayout specificira broj redova i kolona u koje će komponente biti smeštene. Aplet se razbija na matricu ćelija jednakih veličina.

GridLayout je koristan kad se želi razmeštaj više objekata bliskih veličina. Koristi se za sastavljanje liste checkboxova ili radio dugmića.

Primer koji raymešta checkboxove unutar devet redova i jedne kolone, što će apletu dati mnogo bolji i uredniji izgled. Uklonjen je programski kod za obradu događaja jer nije od značaja za ovaj primer.

import java.applet.*; import java.awt.*; public class Sastojci extends Applet {    TextField t;   double cena = 48.00;    public void init() {       this.setLayout(new GridLayout(9,1));       this.add(new Label("Zelite sladoled sa ...?", Label.CENTER));    this.add(new Checkbox("Kakao"));     this.add(new Checkbox("Vanila"));     this.add(new Checkbox("Badem"));     this.add(new Checkbox("Jagoda"));    this.add(new Checkbox("Malaga"));    this.add(new Checkbox("Banana"));     this.add(new Checkbox("Kafa"));     this.t = new TextField("$" + String.valueOf(cena));    this.t.setEditable(false);      this.add(this.t); }

  /* ovde moze doci kod za obradu dogadjaja      koji je iz ovog primera uklonjen */ }    

<HTML> <HEAD></HEAD>

50

<BODY> <P>Izlaz apleta</p>

<P align="center"> <APPLET CODE="Sastojci.class"  WIDTH=400 HEIGHT=400> </APPLET>  

<P>&nbsp;</p>

</BODY> </HTML>  

                 Primer 

Ako se GridLaxout koristi npr. za razmeštaj dugmića, onda se može uočiti da se oni uvećavaju da popune sebi dostupan prostor u svakoj ćeliji. Na primer aplet koji razmešta 9 dugmića u tabelu 3x3 sa 10 piksela razmakom između komponenti u oba pravca:

import java.awt.*;

public class Porodica extends java.applet.Applet {     GridLayout studenti = new GridLayout(3,3,10,10);     Button a1 = new Button("Marko");     Button a2 = new Button("Katarina");     Button a3 = new Button("Goran");     Button a4 = new Button("Janko");     Button a5 = new Button("Ana");     Button a6 = new Button("Petar");     Button a7 = new Button("Sandra");     Button a8 = new Button("Mika");     Button a9 = new Button("Branko");

    public void init() {         setLayout(studenti);         add(a1);         add(a2);         add(a3);         add(a4);         add(a5);         add(a6);         add(a7);         add(a8);

51

        add(a9);     } }  

           Primer 

Ako se aplet Porodica učita u appletviewer-u može se uočiti da u grid razmeštaju komponenta zauzima čitav prostor jedne ćelije, tj. dugmići menjaju veličinu pri promeni veličine Applet prozora, što razlikuje menadžer postavke toka od drugih.

 

2.1.11Razmeštaj tipa GridBagLayout

Klasa java.awt.GridBagLayout daje mrežu za raspoređivanje komponenti, slično kao GridLayout, ali dopušta da pojedina komponenta zauzme više od jedne ćelije. Takođe, ovde se veličina ćelije prilagođava veličini komponente, a ne obrnuto, kao što smo do sada navikli.

Konstruktor za GridBagLayout je trivijalan, GridBagLayout() bez argumenata:      GridBagLayout gbl = new GridBagLayout();

    setLayout(gbl);

Za razliku od upotrebe konstruktora za GridLayout(), ne specificira se  broj redova ili kolona koje treba napraviti. To se određuje prema ćelijama koje konkretni program referencira. Ako npr. stavite komponentu u osmi red i drugu kolonu, Java će osigurati da bude bar devet redova i tri kolone (redovi i kolone se indeksiraju počevod od nulte). Ako kasnije stavite komponentu u deseti red i četvrtu kolonu, Java će dodati odgovarajući broj ćelija. Možete zamišljati konačnu mrežu, ali Java to ne mora znati kad kreirate GridBagLayout.

Za razliku od većine ostalih razmeštaja, referenca na objekt tipa GridBagLayout biće potrebna  kasnije u programu pa ga, dakle nećete kreirati anonimno, unutar poziva metode setLayout().  

2.1.12Specifikacije GridBagConstraints

Svakoj komponenti koju kontroliše GridBagLayout pridružen je po jedan objekt iz klase java.awt.GridBagConstraints koji specificira položaj unutar površine za prikaz. Takav objekt zajedno sa minimalnom i preferiranom veličinom komponente određuje gde se i kako površina za prikaz smešta unutar apleta.

Konstruktor za GridBagConstraints() je trivijalan:

52

GridBagConstraints gbc = new GridBagConstraints();

Interakcija s objektom tipa GridBagConstraints odvija se preko jedanaest promenljivih (gridx, gridy, gridwidth, gridheight, weightx, weighty, achor, fill, insets, ipadx, ipady) i petnaest mnemoničkih konstanti (RELATIVE, REMAINDER, NONE, BOTH, HORIZONTAL, VERTICAL, CENTER, NORTH, NORTHEAST, EAST, SOUTHEAST, SOUTH, SOUTHWEST, WEST, NORTHWEST).

Primer apleta koji predstavlja masku za kalkulator.  

Mreža (grid) za aplet Calculator Evo sada mreže koja se  koristi za razmeštaj kalkulatorovih komponenti. U mreži ima više ćelija nego komponenti kalkulatora. Kalkulator ima jedan TextField i 18 dugmića različitih veličina. Neke komponente zauzeće više od jedne ćelije mreže. Na primer, TextField koji predstavlja kalkulatorov display zauzeće četiri ćelije, (0, 0), (1, 0), (2, 0), and (3, 0).    

(0, 0)  (1, 0)  (2, 0)  (3, 0)

(0, 1)  (1, 1)  (2, 1)  (3. 1)

(0, 2)  (1, 2)  (2, 2)  (3, 2)

(0, 3)  (1, 3)  (2, 3)  (3, 3)

(0, 4)  (1, 4)  (2, 4)  (3, 4)

(0, 5)  (1, 5)

53

 (2, 5)  (3, 5)      

Za svaku komponentu kreiraće se  po jedan objekt tipa GridBagConstraints. Na primer za display, equals key i zero key

     GridBagConstraints GBC_display = new GridBagConstraints();

    GridBagConstraints GBC_bigequals = new GridBagConstraints();

    GridBagConstraints GBC_0 = new GridBagConstraints();

 Nakon što se postave vrednosti odgovarajućih atributa, taj  objekt će se pridružiti komponenti pomoću metode setConstraints() ovako:    

    gbl.setConstraints(display, GBC_display);

    gb1.setConstraints(bigequals, GBC_bigequals;

    gbl.setConstraints(b0, GBC_0);    Atributi gridx i gridy

   Atributi gridx i gridy specificiraju x i y "koordinate", tj. kolonu i vrstu ćelije u koju će doći levi gornji ugao komponente. Gornja leva ćelija u našem primeru je ćelija (0, 0). Umjesto apsolutnih vrednosti možemo staviti i mnemoničku konstantu GridBagConstraints.RELATIVE koja kaže da će komponenta biti smeštena neposredno desno (gridx) ili neposredno ispod (gridy) u odnosu na komponentu koja je pre toga posljednja bila dodana kontejneru.

Naš kalkulator ima display u levom gornjem uglu apleta. Prema tome, gridx i gridy prve komponente (to je TextField) izgledaće:

    GBC_display.gridx = 0;

    GBC_display.gridy = 0;

 Takođe, na primer, taster kalkulatora za znak jednakosti imaće

     GBC_bigequals.gridx = 3;

54

    GBC_bigequals.gridy = 4;

 Taster za cifru 0 imaće

     GBC_0.gridx = 0;

    GBC_0.gridy = 5;    

2.1.13Atributi gridwidth i gridheight

Atributi gridwidth i gridheight specificiraju broj ćelija u vrsti (gridwidth) ili koloni (gridheight) koje će komponenta zauzeti. Ako ovde upišemo mnemoničku konstantu GridBagConstraints.REMAINDER, onda će komponenta zauzeti sve preostale ćelije u vrsti (za gridwidth) ili koloni (za gridheight).

Kalkulatorov display će zauzeti četiri ćelije po širini i jednu po visini:

    GBC_display.gridwidth = 4;    GBC_display.gridheight = 1;

Taster za znak jednakosti (equals key) je dve ćelije visok i jednu ćeliju širok, dakle

     GBC_bigequals.gridwidth = 1;

    GBC_bigequals.gridheight = 2;

 Taster za cifru 0  imaće

     GBC_0.gridwidth = 2;

    GBC_0.gridheight = 1;    

2.1.14Atribut fill

Atribut fill specificira način na koji komponenta ispunjava prostor koji joj je dodeljen (u slučaju da je prostor veći od same komponente). Mnemoničke konstante koje koristite za postavljanje ove promenljive su:

GridBagConstraints.NONE: komponenta ne menja veličinu GridBagConstraints.HORIZONTAL: Komponenta će se protezati preko cele širine prostora koji joj je dodeljen, ali neće promeniti svoju visinu GridBagConstraints.VERTICAL: Komponenta će se protezati preko cele visine prostora koji joj je dodeljen, ali neće promeniti svoju širinu

55

GridBagConstraints.BOTH: Širina i visina komponente biće prilagođene tako da komponenta zauzme celi prostor koji joj je dodeljen U ovom primeru određeno je da se display širi horizontalno, a tasteri u svim smerovima, npr. za taster cifre 0

     GBC_display.fill = GridBagConstraints.HORIZONTAL;    GBC_0.fill = GridBagConstraints.BOTH;  

2.1.15Atributi ipadx i ipady

Svaka komponenta ima određenu minimalnu širinu i visinu i ne može se smanjivati ispod tih vrednosti. Ako su minimalne dimenzije komponente veće od dimenzija površine koje joj stoje na raspolaganju, biće prikazan samo deo komponente.

Atributi ipadx i ipady dozvoljavaju vam da povećate te minimalne dimenzije tako da se rubovima komponente doda nešto prostora . Na primer, ako stavite ipadx =2, to će garantovati da je komponenta najmanje 4 piksela šira od svog normalnog minimuma. U našem primeru to nije potrebno.    

2.1.16Atribut Insets

Atribut insets je instanca klase java.awt.Insets. On specificira razmak između komponente i rubova površine na kojoj je smeštena. Za sve tastere u kalkulatoru odredili smo da to bude 3 piksela sa svake strane (što osigurava da susedni tasteri budu razmaknuti za 6 piksela), pa imamo na primer

     GBC_bigequals.insets = new Insets(3, 3, 3, 3);

    GBC_0.insets = new Insets(3, 3, 3, 3);  

2.1.17Atribut anchor

Kad je komponenta manje nego raspoloživa površina, atribut anchor specificira položaj unutar ćelije gde će komponentu postaviti. Mnemoničke konstante koje se za to koriste slične su onima za BorderLayout. To su

56

2.1.18GridBagConstraints.CENTER GridBagConstraints.NORTH GridBagConstraints.NORTHEAST GridBagConstraints.EAST GridBagConstraints.SOUTHEAST GridBagConstraints.SOUTH GridBagConstraints.SOUTHWEST GridBagConstraints.WEST GridBagConstraints.NORTHWEST Pretpostavljena vrednost je GridBagConstraints.CENTER. U tekućem primeru to nije eksplicitno navedeno, jer su komponente dovoljno velike u odnosu na raspoložive površine, tako da je centrirana pozicija zadovoljavajuća.    

2.1.19Atributi weightx i weighty

Atributi weightx i weighty određuju kako su ćelije distribuirane unutar kontejnera ako njihova ukupna veličina bude manja od veličine kontejnera. Sa težinama 0 (default) sve ćelije zauzimaju najmanje što mogu i sve se sabije prema centru. Sav dodatni prostor je izguran prema rubovima kontejnera.    

Primer za GridBagLayout Pogledajmo sada  init() metod  sa razmeštajem kalkulatorovih tastera:

   public void init () {

    GridBagLayout gbl = new GridBagLayout();

    setLayout(gbl);    

    // dodavanje displeja za gornje četiri ćelije

    GridBagConstraints GBC_display = new GridBagConstraints();

    GBC_display.gridx = 0;

    GBC_display.gridy = 0;

57

    GBC_display.gridwidth = 4;

    GBC_display.gridheight = 1;

    GBC_display.fill = GridBagConstraints.HORIZONTAL;    

    // dodavanje tekstualnog polja

    TextField display = new TextField(12);

    gbl.setConstraints(display, GBC_display);

    add(display);    

    // dodavanje claer tastera kalkulatora

    GridBagConstraints GBC_clear = new GridBagConstraints();

    GBC_clear.gridx = 0;

    GBC_clear.gridy = 1;

    GBC_clear.gridwidth = 1;

    GBC_clear.gridheight = 1;

    GBC_clear.fill = GridBagConstraints.BOTH;

    GBC_clear.insets = new Insets(3, 3, 3, 3);    

    // dodavanje dugmića

    Button clear = new Button("C");

    gbl.setConstraints(clear, GBC_clear);

    add(clear);    

58

   

    // dodavanje znaka jednakosti

    GridBagConstraints GBC_equals = new GridBagConstraints();

    GBC_equals.gridx = 1;

    GBC_equals.gridy = 1;

    GBC_equals.gridwidth = 1;

    GBC_equals.gridheight = 1;

    GBC_equals.fill = GridBagConstraints.BOTH;

    GBC_equals.insets = new Insets(3, 3, 3, 3);    

    // dodavanje dugmeta =

    Button equals = new Button("=");

    gbl.setConstraints(equals, GBC_equals);

    add(equals);    

    // dodavanje dugmeta /

    GridBagConstraints GBC_slash = new GridBagConstraints();

    GBC_slash.gridx = 2;

    GBC_slash.gridy = 1;

    GBC_slash.gridwidth = 1;

    GBC_slash.gridheight = 1;

    GBC_slash.fill = GridBagConstraints.BOTH;

59

    GBC_slash.insets = new Insets(3, 3, 3, 3);    

    // dugme /

    Button slash = new Button("/");

    gbl.setConstraints(slash, GBC_slash);

    add(slash);        

    // taster *

    GridBagConstraints GBC_times = new GridBagConstraints();

    GBC_times.gridx = 3;

    GBC_times.gridy = 1;

    GBC_times.gridwidth = 1;

    GBC_times.gridheight = 1;

    GBC_times.fill = GridBagConstraints.BOTH;

    GBC_times.insets = new Insets(3, 3, 3, 3);    

    // dodavanje dugmeta *

    Button star = new Button("*");

    gbl.setConstraints(star, GBC_times);

    add(star);    

    // taster 7

60

    GridBagConstraints GBC_7 = new GridBagConstraints();

    GBC_7.gridx = 0;

    GBC_7.gridy = 2;

    GBC_7.gridwidth = 1;

    GBC_7.gridheight = 1;

    GBC_7.fill = GridBagConstraints.BOTH;

    GBC_7.insets = new Insets(3, 3, 3, 3);    

    // dodavanje dugmeta

    Button b7 = new Button("7");

    gbl.setConstraints(b7, GBC_7);

    add(b7);        

    // taster  8

    GridBagConstraints GBC_8 = new GridBagConstraints();

    GBC_8.gridx = 1;

    GBC_8.gridy = 2;

    GBC_8.gridwidth = 1;

    GBC_8.gridheight = 1;

    GBC_8.fill = GridBagConstraints.BOTH;

    GBC_8.insets = new Insets(3, 3, 3, 3);      

61

    Button b8 = new Button("8");

    gbl.setConstraints(b8, GBC_8);

    add(b8);      

    GridBagConstraints GBC_9 = new GridBagConstraints();

    GBC_9.gridx = 2;

    GBC_9.gridy = 2;

    GBC_9.gridwidth = 1;

    GBC_9.gridheight = 1;

    GBC_9.fill = GridBagConstraints.BOTH;

    GBC_9.insets = new Insets(3, 3, 3, 3);      

    Button b9 = new Button("9");

    gbl.setConstraints(b9, GBC_9);

    add(b9);        

    // taster -

    GridBagConstraints GBC_minus = new GridBagConstraints();

    GBC_minus.gridx = 3;

    GBC_minus.gridy = 2;

    GBC_minus.gridwidth = 1;

62

    GBC_minus.gridheight = 1;

    GBC_minus.fill = GridBagConstraints.BOTH;

    GBC_minus.insets = new Insets(3, 3, 3, 3);    

    // dodavanje dugmeta

    Button minus = new Button("-");

    gbl.setConstraints(minus, GBC_minus);

    add(minus);    

    //  4

    GridBagConstraints GBC_4 = new GridBagConstraints();

    GBC_4.gridx = 0;

    GBC_4.gridy = 3;

    GBC_4.gridwidth = 1;

    GBC_4.gridheight = 1;

    GBC_4.fill = GridBagConstraints.BOTH;

    GBC_4.insets = new Insets(3, 3, 3, 3);      

    Button b4 = new Button("4");

    gbl.setConstraints(b4, GBC_4);

    add(b4);      

63

   

    GridBagConstraints GBC_5 = new GridBagConstraints();

    GBC_5.gridx = 1;

    GBC_5.gridy = 3;

    GBC_5.gridwidth = 1;

    GBC_5.gridheight = 1;

    GBC_5.fill = GridBagConstraints.BOTH;

    GBC_5.insets = new Insets(3, 3, 3, 3);      

    Button b5 = new Button("5");

    gbl.setConstraints(b5, GBC_5);

    add(b5);      

    GridBagConstraints GBC_6 = new GridBagConstraints();

    GBC_6.gridx = 2;

    GBC_6.gridy = 3;

    GBC_6.gridwidth = 1;

    GBC_6.gridheight = 1;

    GBC_6.fill = GridBagConstraints.BOTH;

    GBC_6.insets = new Insets(3, 3, 3, 3);      

64

    Button b6 = new Button("6");

    gbl.setConstraints(b6, GBC_6);

    add(b6);        

    // taster +

    GridBagConstraints GBC_plus = new GridBagConstraints();

    GBC_plus.gridx = 3;

    GBC_plus.gridy = 3;

    GBC_plus.gridwidth = 1;

    GBC_plus.gridheight = 1;

    GBC_plus.fill = GridBagConstraints.BOTH;

    GBC_plus.insets = new Insets(3, 3, 3, 3);      

    Button plus = new Button("+");

    gbl.setConstraints(plus, GBC_plus);

    add(plus);      

    GridBagConstraints GBC_1 = new GridBagConstraints();

    GBC_1.gridx = 0;

    GBC_1.gridy = 4;

    GBC_1.gridwidth = 1;

65

    GBC_1.gridheight = 1;

    GBC_1.fill = GridBagConstraints.BOTH;

    GBC_1.insets = new Insets(3, 3, 3, 3);      

    Button b1 = new Button("1");

    gbl.setConstraints(b1, GBC_1);

    add(b1);          

    GridBagConstraints GBC_2 = new GridBagConstraints();

    GBC_2.gridx = 1;

    GBC_2.gridy = 4;

    GBC_2.gridwidth = 1;

    GBC_2.gridheight = 1;

    GBC_2.fill = GridBagConstraints.BOTH;

    GBC_2.insets = new Insets(3, 3, 3, 3);      

    Button b2 = new Button("2");

    gbl.setConstraints(b2, GBC_2);

    add(b2);      

66

    GridBagConstraints GBC_3 = new GridBagConstraints();

    GBC_3.gridx = 2;

    GBC_3.gridy = 4;

    GBC_3.gridwidth = 1;

    GBC_3.gridheight = 1;

    GBC_3.fill = GridBagConstraints.BOTH;

    GBC_3.insets = new Insets(3, 3, 3, 3);      

    Button b3 = new Button("3");

    gbl.setConstraints(b3, GBC_3);

    add(b3);          

    GridBagConstraints GBC_bigequals = new GridBagConstraints();

    GBC_bigequals.gridx = 3;

    GBC_bigequals.gridy = 4;

    GBC_bigequals.gridwidth = 1;

    GBC_bigequals.gridheight = 2;

    GBC_bigequals.fill = GridBagConstraints.BOTH;

    GBC_bigequals.insets = new Insets(3, 3, 3, 3);      

    Button bigequals = new Button("=");

67

    gbl.setConstraints(bigequals, GBC_bigequals);

    add(bigequals);      

    GridBagConstraints GBC_0 = new GridBagConstraints();

    GBC_0.gridx = 0;

    GBC_0.gridy = 5;

    GBC_0.gridwidth = 2;

    GBC_0.gridheight = 1;

    GBC_0.fill = GridBagConstraints.BOTH;

    GBC_0.insets = new Insets(3, 3, 3, 3);      

    Button b0 = new Button("0");

    gbl.setConstraints(b0, GBC_0);

    add(b0);          

    GridBagConstraints GBC_decimal = new GridBagConstraints();

    GBC_decimal.gridx = 2;

    GBC_decimal.gridy = 5;

    GBC_decimal.gridwidth = 1;

    GBC_decimal.gridheight = 1;

    GBC_decimal.fill = GridBagConstraints.BOTH;

68

    GBC_decimal.insets = new Insets(3, 3, 3, 3);      

    Button bdecimal = new Button(".");

    gbl.setConstraints(bdecimal, GBC_decimal);

    add(bdecimal);    

  }

2.1.20Šta je Container?

Kontejner je komponenta koja može sadržati druge komponente. On je uvek instanca klase java.awt.Container koja je podklasa od java.awt.Component, pa su, dakle, kontejneri i sami  komponente.

Applet je primer kontejnera, kao  i prozori (windows), okviri (frames), dijalozi (dialogs) i paneli (panels). Kontejneri mogu sadržati druge kontejnere.

Svaki kontejner ima svoj Layout manager koji određuje način pozicioniranja komponenata unutar kontejnera.

Apleti osiguravaju već gotov kontejner i pretpostavljeni Layout manager. To je FlowLayout.

Paneli su podklase od java.awt.Panel. Panel se nalazi unutar drugog kontejnera ili možda unutar browserovog prozora. Paneli nisu samostalni. Appleti su primer panela.

Prozori su podklase od java.awt.Window. Prozor je samostalan. Postoji više vrsta prozora, na primer okviri (frames) i dijalozi(dialogs). Okviri su podklase od java.awt.Frame. Klasa Frame daje proyor sa naslovnom trakom, dugmad za zatvaranje prozora i ostale mogućnosti prozora vezanig za platformu (operativni sistem). Okviri omogućuju i dodavanje menija.  Dijalozi su podklase od java.awt.Dialog. Dialog je privremeni, nestalni prozor koji postoji samo da prenese neke informacije ili primi neki ulaz od korisnika. Na primer, FileDialog je podklasa klase Dialog koja omogućava standardne dijalog boksove za selekciju datoteka. Obično se koristi u Java aplikacijama zbog sigurnosnih ograničenja apleta.  

69

Paneli Svaki Panel je zapravo generički Container čija glavna uloga je grupisanje komponenti na jedno mesto. Pri radu sa panelima važno je znati je da

panel bude popunjen komponentama pre nego se smesti u veći kontejner panel ima svoj sopstveni LayoutManager

Paneli se kreiraju poyivom konstruktora Panel  klase:  Panel mojPanel=new Panel();

Metod postavke za panel se određuje pozivom setLayout() metoda na tom panelu. Funkcionisanje je isto kao kod istoimenog metoda primenjenog na aplet prozor, jer i Applet  i Panel predstavljaju podklase Container klase i nasleđuju neporomenjeno ponašanje iz te superklase.

Kako svaki Panel može imati sopstveni LayoutManager, onda se sa panelima možete učiniti mnogo toga što inače nije moguće sa samo jednim Layout managerom.

Na primer, pretpostavimo da želite da se TextArea nalazi u centru appleta, a dugme ispod nje, na "jugu":

To se ne možete postići s jednim jedinim Layout managerom. Na primer, BorderLayout bi proširio Button preko čitave širine appleta. S druge strane FlowLayout ne bi učinio da TextArea bude dovoljno velika.

Umesto toga, može se kreirati aplet koji ima BorderLayout, a TextArea mu se nalazi u centru. Potom kreirati Panel, postavite njegov LayoutManager na FlowLayout, dodate button tom panelu i onda dodati panel južnom delu appleta. Evo primera:  

 import java.applet.*;  import java.awt.*;    public class Panel1 extends Applet {

   public void init() {     this.setLayout(new BorderLayout());    this.add("Center", new TextArea());        Panel p = new Panel();    p.setLayout(new FlowLayout(FlowLayout.CENTER));    p.add(new Button("OK"));    this.add("South", p);      }

70

}  

<APPLET CODE="Panel1.class"  WIDTH=300 HEIGHT=200>

</APPLET>

 U ovom primeru bitno je  razlikovati dodavanje komponente apletu (add(...) ili this.add(...)) od dodavanja komponente panelu (p.add(...)).

Ali, nije od značaja da li je prvo dodat panel appletu, pa onda button panelu ili obrnuto.

Druga česta upotreba panela je za postavljanje niza checkboxova koji imaju GridLayout s jednom kolonom.     Ugnježdeni paneli Ponekad je potrebno nekoliko instanci istog LayoutManagera. Pogledajmo opet primer kalkulatora.

S jedne strane izgleda kao da ga je jednostavno implementirati, jer se radi sa  18 Button-a i TextField-om. S druge strane, gotovo svi tasteri su jednake veličine, samo su dva tastera i display nešto veći. Gotovo bi se mogao koristiti GridLayout, ali ipak ne sasvim. Paneli su jedan od načina rešavanja ovog problema.

Evo sada rešenja kalkulatora uz upotrebu samo GridLayout i ugnježdenih panela.

 import java.applet.*;  import java.awt.*;  public class Calculator extends Applet {   TextField screen;

  public void init () {     this.setLayout(new GridLayout(3, 1, 3, 3));    Panel A1 = new Panel();    this.add(A1);    Panel A2 = new Panel();    this.add(A2);    Panel A3 = new Panel();    this.add(A3);

    A1.setLayout(new GridLayout(2, 1));    screen = new TextField(12);    A1.add(screen);

   Panel B1 = new Panel();    B1.setLayout(new GridLayout(1, 4, 3, 3));    B1.add(new Button("C"));    B1.add(new Button("="));    B1.add(new Button("/"));    B1.add(new Button("*"));     A1.add(B1);

71

    A2.setLayout(new GridLayout(2, 4, 3, 3));     A2.add(new Button("7"));    A2.add(new Button("8"));    A2.add(new Button("9"));    A2.add(new Button("-"));     A2.add(new Button("4"));    A2.add(new Button("5"));    A2.add(new Button("6"));    A2.add(new Button("+"));

   A3.setLayout(new GridLayout(1, 2, 3, 3));    // 1, 2 and 0    Panel B2 = new Panel();    B2.setLayout(new GridLayout(2, 1, 3, 3));    // 1 and 2    Panel C1 = new Panel();    C1.setLayout(new GridLayout(1, 2, 3, 3));    C1.add(new Button("1"));    C1.add(new Button("2"));    B2.add(C1);    B2.add(new Button("0"));    // 3, . and =   Panel     B3 = new Panel();    B3.setLayout(new GridLayout(1, 2, 3, 3));    // 3 and .   Panel C2 = new Panel();    C2.setLayout(new GridLayout(2, 1, 3, 3));    C2.add(new Button("3"));   C2.add(new Button("."));    B3.add(C2);    B3.add(new Button("="));    A3.add(B2);    A3.add(B3);   }

  public Insets insets() {      return new Insets(5, 5, 5, 5);    }

  /*  event handling Jave 1.0 . */  public boolean action(Event e, Object arg) {    if (e.target instanceof Button) {      screen.setText((String) arg);      return true;    }    return false;    }

}

<APPLET CODE="Calculator.class" WIDTH=150 HEIGHT=150>

</APPLET>     Prozori (windows) Klasa java.awt.Window i njene podklase omogućuju kreiranje samostalnih prozora. Samostalni prozori su česti u aplikacijama koje za komunikaciju s korisnikom koriste AWT umesto komandne linije. Takođe osiguravaju dodatni prostor za applete.

Klasa java.awt.Window je podklasa od java.awt.Container, ali je nezavisna od ostalih kontejnera, tj. sam nije sadržan u drugim kontejnerima. Možete mu dodavati komponente kao što je Button ili TextField. Može imati svoj vlastiti LayoutManager. Možete crtati direktno pomoću njegove paint() metode. Sve što možete raditi u appletovom panelu, možete raditi i u prozoru.

72

Uobičajeno je da se klasa java.awt.Window ne koristi direktno. Umesto toga radi se sa njenim podklasama, na primer java.awt.Frame ili java.awt.Dialog, zavisno od vaših potreba. Frame je okvir koji može imati svoj scrollbar, korisnik mu može menjati veličinu ili položaj i postojaće na ekranu dok god korisnika zanima njegov sadržaj.

Nasuprot tome, dijalog neće imati meni, obično mu se ne može menjati veličina iako je moguće pomerati ga. Njegova funkcija je prenošenje određene informacije (unosa) od korisnika ili izdavanje upozorenja. Vidljiv je samo dok ne dobije odgovarajući input ili dok korisnik ne potvrdi da je pročitao informaciju s njega.  

Okviri (frames) Okviri su korisni za kompleksnije aplikacije. Omogućuju odvajanje različitih funkcija ili podataka u različite prozore. Na primer, aplikacija za crtanje može imati nekoliko različitih slika s raznim statusima završenosti u različitim prozorima. Ili možda može imati jednu sliku, ali u drugom prozoru paletu s raznim četkama i bojama. Svaki od tih prozora bio bi Frame.

Sve što je potrebno za kreiranje okvira i rad s njima nalazi se u klasi java.awt.Frame. Za kreiranje novog okvira bez naslovne pruge koristi se konstruktor Frame() bez argumenata.

Frame f = new Frame();

Češće će ipak biti potrebno dati okviru naslov:  Frame f = new Frame("Moj Prozor");

Okviri nasleđuju klasu java.awt.Container, te im se mogu dodavati komponente. Za razliku od panela i appleta, pretpostavljeni LayoutManager za okvire je BorderLayout, a ne FlowLayout. To se , naravno, može izmeniti pomoću metode setLayout():                 f.setLayout(new FlowLayout());

Okviri nasleđuju i klasu java.awt.Component, te imaju i metode paint() i update(). Ako se želi crtati unutar okvira i procesirati događaj ručno kao u appletima, onda se kreira podklasa od Frame i dodaje  joj se odgovarajući listener. Uglavnom sve što je rađeno sa vlastitim podklasama od java.awt.Applet može se raditi i sa sopstvenim podklasama od java.awt.Frame.

Ali, najčešće se koriste komponente. Da bi se komponenta dodala okviru, poziva se njegova metodu  add() isto kao što je pozivana appletova metoda  add(). Jedina razlika je što često se ta metoda  poziva izvan klase Frame, tako da će biti potrebno dodati odgovarajući prefiks koji pokazuje na okvir. Drugim rečima, ako postoji okvir Frame f, poziva se f.add(new Button("OK"); umesto this.add(new Button("OK"));

Naravno, to zavisi koja klasa je tekuća klasa kad pozivate add(). Ako je pozivate iz neke od podklasa klase Frame, onda to neće biti potrebno.

73

Kako je pretpostavljeni layout za frame BorderLayout, potrebno je specificirati da li komponentu dodajete na North, South, East, West ili Center. Evo primera koji pokazuje kako se dodaje centrirana labela u centar okvira Frame f:                      f.add("Center", new Label("Ovo jeste okvir", Label.CENTER)); Ili f.add(new Label("Ovo jeste okvir", Label.CENTER), BorderLayout.CENTER);

Veličina i pozicija bilo kojeg datog okvira je nepredvidljiva ako se ne specificirate. Veličina se zadaje pomoću metode setSize():                                     f.setSize(150,150);

Ta veličina ne uključuje naslovnu prugu, pa to treba zasebno uzeti u obzir. Da biste doznali visinu naslovne pruge za okvir, poziva se njegov metod insets() i pogledati atribut top rezultirajućeg objekta iz java.awt.Insets. To će biti visina naslovne pruge:           int TitleBarVisina = f.insets().top;

Postavljanje okvira na željenu poziciju na ekranu obavlja se pomoću metode setLocation(int x, int y). Ovdje se x i y računaju prema ekranu, ne prema appletu.

Kad se prozor kreira, on je u početku nevidljiv. Dodavanje komponenti dobro je obaviti dok je prozor još nevidljiv, inače će korisnik morati gledati skakanje komponenti i nepredvidljivo pomicanje prozora dok se slika ne stabilizuje. Kad ste završili s dodavanjem komponenti, okvir se mora učiniti vidljivim pozivom metoda show():   f.show();

Događaji vezani uz prozore Budući da je java.awt.Window podklasa od java.awt.Component, znači da objekti tipa Window mogu lansirati događaje. Ti događaji su objekti tipa java.awt.event.WindowEvent. To su:

WindowEvent.WINDOW_ACTIVATED WindowEvent.WINDOW_CLOSED WindowEvent.WINDOW_CLOSING WindowEvent.WINDOW_DEACTIVATED WindowEvent.WINDOW_DEICONIFIED WindowEvent.WINDOW_ICONIFIED WindowEvent.WINDOW_OPENED

Da biste mogli odgovarati na te događaje, morate uz objekt tipa java.awt.Window registrovati odgovarajući listener, dakle objekt neke klase koja implementira interface java.awt.event.WindowListener. Ovaj interfejs propisuje sledeće metode:

   public abstract void windowOpened(WindowEvent e)    public abstract void windowClosing(WindowEvent e)    public abstract void windowClosed(WindowEvent e)    public abstract void windowIconified(WindowEvent e)    public abstract void windowDeiconified(WindowEvent e)

74

   public abstract void windowActivated(WindowEvent e)    public abstract void windowDeactivated(WindowEvent e)      

Primer događaja na prozorima Na primer, prozori se ne zatvaraju sami od sebe nego se moraju eksplicitno zatvoriti. Sledeća podklasa klase Frame odgovara na pokušaj zatvaranja tako da pozove metode setVisible(false) i dispose().

 import java.awt.*; import java.awt.event.*;  public class ZatvorenFrame extends Frame implements WindowListener {

  public ZatvorenFrame() {    this.addWindowListener(this);  }

   public ZatvorenFrame(String s) {       super(s);       this.addWindowListener(this);  }

   public void windowClosing(WindowEvent e) {       this.setVisible(false);       this.dispose();  }

   public void windowOpened(WindowEvent e) {}    public void windowClosed(WindowEvent e) {}    public void windowIconified(WindowEvent e) {}    public void windowDeiconified(WindowEvent e) {}    public void windowActivated(WindowEvent e) {}    public void windowDeactivated(WindowEvent e) {} }  

Može se aktivirati pomoću sledećeg apleta:

 import java.applet.Applet;

import java.awt.*;

 public class ZatvorenFrameApplet extends Applet {

75

   public void init() {

    ZatvorenFrame cf = new ZatvorenFrame();

    cf.setSize(150,150);

    cf.setLocation(100,100);

    cf.show();   }

}    

<APPLET CODE="ZatvorenFrameApplet.class"  WIDTH=200 HEIGHT=100>

</APPLET>    

Kombinovanje apleta i aplikacija Apletu je potreban okvir da bi se izvršavao koji po pravilu obezbeđuje web browser.Ali mogu se kreirati instance korisničkog appleta unutar nekog okvira korisničke aplikacije. Na taj način može se pisati kod koji je istovremeno i applet i aplikacija.

Da bi se applet pretvorio u aplikaciju, dodaje mu se sledeća main() metodu (smatrati da mojApplet je naziv korisničkog appleta):

public static void main(String args[]) {      mojApplet a = new mojApplet();     a.init();     a.start();    Frame appletFrame = new Frame("Applet Prozor");    appletFrame.add("Center", a);  appletFrame.setSize(150,150);  appletFrame.setLocation(100,100);  appletFrame.show(); }

U prvom redu nalazi se deklaracija standardne main() metode koja se  koristi za aplikacije pokretane iz  komandne linije. Ako se applet izvršava unutar web browsera ili applet viewera, taj metod biće ignorisan. Izvršiće se samo ako se applet pokrene kao samostalni program.

76

Red 2 kreira instancu korisničkog appleta. U redovima 3 i 4 poziva se appletov init() i start() metod. To inače radi web browser za vas, ali ako se program izvršava samostalno, morate to sami učiniti.

Nakon što je kreiran aplet, potreban je Frame u koji ćete ga smestiti. U redu 5  to se obavlja pomoću uobičajenog konstruktora Frame(). Ovde se možete promeniti naslov okvira da odgovara korisničkoj aplikaciji.

U redu 6 dodaje se applet u taj Frame. Budući da je LayoutManager za Frame po pretpostavci BorderLayout, applet će biti dodan u centar. Inače, java.applet.Applet je podklasa od java.awt.Component pa je u redu dodati ga na neki Frame.

Red 7 zadaje veličinu za Frame:150 x 150 pixela. Ako se program izvršava kao applet, te vrednosti se mogu dobiti iz parametara width i height, ali ako se izvršava samostalno, morate osmisliti neke veličine. Možete ih eventualno učitati kao argumente s komandne linije.

Red 8 postavlja Frame na poziciju (100, 100). Ako poziciju sami ne zadate, ona će biti nepredvidljiva,

Red 9 čini Frame vidljivim i applet je sad spreman za izvršavanje, unutar browsera ili izvan njega.

Napomena: Čak i ako imaju Frame, appleti ipak nisu isto što i aplikacije. Kad se applet transformiše u aplikaciju na opisani način, mora se osigurati da se program ne oslanja na metode koje imaju smisla jedino u appletima. Na primer, metoda getParameter() nema smisla izvan appleta. Isto tako, argumente s komandne linije možete učitavati samo u aplikacijama. Nadalje, aplikacije imaju manje sigurnosnih restrikcija nego appleti pa program koji dobro radi kao aplikacija može proizvesti mnoštvo sigurnosnih izuzetaka (java.lang.SecurityException).  

Dijalozi Okviri su korisni kao prozori koji će se neko vreme zadržati na ekranu, na primer u svrhu editovanja nekog teksta i slično. Za razliku od njih, dijalozi koje implementira klasa java.awt.Dialog, po prirodi su kratkotrajni i služe samo kao sredstvo za kratki input ili upozorenje korisniku.

Slično kao java.awt.Frame, java.awt.Dialog je podklasa od java.awt.Window pa dakle i od java.awt.Container i java.awt.Component. Prema tome, mnogo toga što znate o okvirima primjenjuje se i na dijaloge. Možete ih pomerati, menjati im veličinu i dodavati im komponente skoro isto kao i u slučaju okvira. Postoje, međutim, dve značajne razlike:

Okvir (frame) može imati prugu menija (menu bar) dok dijalog to ne može Dijalog može biti modalan, dok okvir ne može Modalni dijalog blokira komunikaciju sa svim drugim aplikacijama sve dok ne dobije odgovarajući input od korisnika. Ne može se pomerati i ne dozvoljava korisniku prelaz u drugi prozor istog programa. Na nekim platformama ne dozvoljava čak i odlazak u prozore drugih

77

programa.  Ne-modalni dijalozi se postavljaju pri aktiviranju, ali ne sprečavaju korisnika da radi druge stvari dok su oni vidljivi.

Metode za dijaloge Budući da su dijalozi komponente, oni mogu, kao i okviri, koristiti metode kao što su setLocation() ili setSize(). Za dijaloge imamo konstruktore koji im daju ili ne daju naslov, pa možemo, staviti:

 Dialog d = new Dialog(new Frame(), false); Prvi argument je roditeljski frame za taj dijalog, dok je drugi  tipa boolean i određuje hoće li dijalog biti modalan (true) ili ne (false). Modalni dijalozi su modalni u odnosu na svoj roditeljski frame, dakle privremeno sprečavaju unos u taj okvir, ali ne i u druge okvire.

Ako za prvi argument stavite null dijalog će izbaciti izuzetak, java.lang.IllegalArgumentException.

Ako kreirate roditeljski frame direktno unutar poziva konstruktora kao u prethodnom primeru, dijalog ne može biti modalan.

Ima još i nekih manjih razlika između okvira i dijaloga, npr.:

Korisnik može menjati položaj i veličinu većini okvira, dok dijalozima u pravilu ne može. Okviri obično imaju naslovne pruge. Dijalogu možete omogućiti promenjivost veličine pomoću metode setResizable():  d.setResizable(true); Možete mu dati naslovnu prugu tako da ga kreirate pomoću sledećeg konstruktora::  Dialog d = new Dialog(new Frame(), "Moj Dialog Prozor", false);

Sve ostale metode i postupci za dijaloge isti su kao i za okvire.    

Sledeći primer prikazuje jednostavni ne-modalni dijalog sa OK buttonom i bez naslovne pruge.

 import java.applet.*; import java.awt.*;  public class DialogPrimer extends Applet {

  public void init() {        Dialog mojDialog = new Dialog(new Frame(), false);    mojDialog.setLocation(320,240);    myDialog.add("North", new Label("Pozdrav!"));    myDialog.add("South", new Button("OK"));    myDialog.pack();    myDialog.show();

78

     }  }

<APPLET CODE="DialogPrimer.class" WIDTH=150 HEIGHT=150>

</APPLET>    

Pisanje podklasa klase Dialog Prethodni primer je bio samo ilustracije radi, jer po pravilu, najčešća upotreba dijaloga je putem kreiranja vlastitih podklasa od java.awt.Dialog i i instanciranja  iz glavnog programa. Na primer, jedan od jednostavnijih uobičajenih dijaloga je ispis poruke koju korisnik treba pročitati i potvrditi to pritiskom na OK dugme:

 import java.awt.*;

import java.awt.event.*;

public class YesNoDialog extends Dialog implements ActionListener {

   public YesNoDialog(Frame parent, String message) {

     super(parent, true);

    this.add("Center", new Label(message));

    Panel p = new Panel();

    p.setLayout(new FlowLayout());

    Button yes = new Button("Yes");

    yes.addActionListener(this);

    p.add(yes);

    Button no = new Button("No");

    no.addActionListener(this);

    p.add(no);

    this.add("South", p);

79

    this.setSize(350,100);

    this.setLocation(100, 200);

    }    

  public void actionPerformed(ActionEvent e) {

    this.setVisible(false);

    this.dispose();

  }    

}    

import java.applet.Applet;

import java.awt.*;    

public class Upozorenje1 extends Applet {    

  public void init () {    

    Dialog d = new YesNoDialog(new Frame(),

     "Da li ste sigurni da nikad necete programirati?");

    d.show();     } }    

80

<APPLET CODE="Upozorenje1.class" WIDTH=300 HEIGHT=200>

</APPLET>  

Šta je meni? Java omogućuje postavljanje menija na frameove (dijalozima se meniji ne mogu dodavati). Za applete to i nije tako bitno, ali u aplikacijama je najčešće nužno.

Meniji su sastavljeni od tri hijerarhijska elementa Prvi element je pruga ili traka menija (menu bar). To je set menija koji se pojavljuju duž prozora.Nalazi se na gornjem rubu ekrana kod Macintosha ili na gornjem rubu prozora kod Windowsa ili Motifa.

Svaka pruga menija sadrži bar jedan meni (menu). Meni su organizirani poi temama. Često susrećemo File, Edit i tako dalje.

Svaki meni sadrži bar jednu opciju (menu item). Opcije su obično pojedinačne akcije kao Open, Print, Cut ili Copy. Opcije nisu prikazane dok meni nije aktivan. Dva ili više menija ne mogu biti istovremeno aktivni.

Klase menija Paket AWT sadrži nekoliko glavnih klasa za upravljanje menijima:

java.awt.Menu java.awt.MenuBar java.awt.MenuItem java.awt.PopupMenu

Da bi se koristili meniji, biće potreban bar jedan primerak iz klase MenuBar sa jednim ili više primeraka klase Menu, a za svakog nekoliko primeraka MenuItem. Meniji iz klase PopupMenu se pojavljuju kao samostalni element.

 Klasa java.awt.MenuComponent je poslednja nadklasa svih ovih klasa, a ona je opet podklasa od java.lang.Object. Prema tome, pruge menija, izbornici i opcije nisu komponente i ne mogu se dodavati kontejnerima na uobičajeni način.  

java.lang.Object    |    +--java.awt.MenuComponent            |            +--java.awt.MenuBar            |            +--java.awt.MenuItem                      |

81

                     +--java.awt.Menu                                |                                +--java.awt.PopupMenu

Uošava se da su MenuBar i MenuItem podklase od MenuComponent. Menu je podklasa od MenuItem (ovo zvuči malo neobično, ali meni je zaista opcija, samo se dodaje pruzi menija). Nadalje, MenuBar implementira interface java.awt.MenuContainer.    

Kreiranje menija Poželjno je potpuno izgraditi menije pre nego ih prikažete. Tipični redosled akcija je:

kreirajte novi objekt tipa MenuBar. kreirajte novi objekt tipa Menu. dodajte opcije objektu tipa Menu. ako je potrebno, ponovite korake 2 i 3. dodajte objekt tipa MenuBar objektu tipa Frame.

Novi objekt tipa MenuBar kreira se ovako:     MenuBar myMenubar = new MenuBar();

Za kreiranje novog objekta tipa Menu koristi se konstruktor Menu(String title). Dodajte mu naslov koji želite dati meniju. Na primer, za kreiranje menija File i Edit, napravite:  

    Menu fileMenu = new Menu("File");     Menu editMenu = new Menu("Edit");

Opcije, MenuItema kreiraju se slično, pomoću konstruktora MenuItem(String menutext). Dajte mu potreban naslov, na primer:  

    MenuItem Cut = new MenuItem("Cut");

Objekte tipa MenuItem kreirate unutar odgovarajućih objekata tipa Menu kojima pripadaju, isto kao što ste komponente kreirali unutar odgovarajućih razmeštaja. Izbornici imaju add() metode koje kao argument uzimaju objekte tipa MenuItem. Evo kako biste napravili meni Edit  i dodali mu opcije Undo, Cut, Copy, Paste, Clear i Select All:  

    Menu editMenu = new Menu("Edit");

    editMenu.add(new MenuItem("Undo"));

    editMenu.addSeparator();

82

    editMenu.add(new MenuItem("Cut"));     editMenu.add(new MenuItem("Copy"));     editMenu.add(new MenuItem("Paste"));     editMenu.add(new MenuItem("Clear"));

    editMenu.addSeparator();

    editMenu.add(new MenuItem("Select All"));

Metoda addSeparator() dodaje horizontalnu crtu preko izbornika. Koristi se za logičko razdvajanje funkcija na meniju.

Kad kreirate menije, dakle objekte tipa Menu, dodaćete ih pruzi menija, objektu tipa MenuBar koristeći MenuBarovu metodu add(Menu m) ovako:

    myMenubar.add(fileMenu);     myMenubar.add(editMenu);

Konačno, kad je MenuBar gotov, dodaćete ga okviru, dakle objektu tipa Frame koristeći se frameovom metodom setMenuBar(MenuBar mb). Ako imate Frame f onda bi to izgledalo ovako:

 

    f.setMenuBar(myMenuBar);  

Primer menija  Korisnički interfejs može imati mnogo opcija, čak i po više stotina. Sve njih staviti u init() metodu bilo bi nepraktično. Uobičajeno je kreirati odvojene metode koje grade pojedinačni meni i dodati ih pruzi menija. Sledeći primer kreira dva standardna izbornika, File i Edit.  

import java.applet.*; import java.awt.*;  

public class MenuPrimer extends Applet {

  public void init () {

    Frame f = new Frame("Prozor s menijem");     f.add("Center", new Label("Pogledajte meni", Label.CENTER));     f.setSize(this.getSize().width, this.getSize().height);     f.setLocation(320,240);     MenuBar myMenuBar = new MenuBar();     this.makeFileMenu(myMenuBar);

83

    this.makeEditMenu(myMenuBar);     f.setMenuBar(myMenuBar);     f.show();

  }

  void makeEditMenu(MenuBar mb) {

    Menu editMenu = new Menu("Edit");     editMenu.add("Undo");     editMenu.addSeparator();     editMenu.add("Cut");     editMenu.add("Copy");     editMenu.add("Paste");     editMenu.add("Clear");     mb.add(editMenu);

  }

  void makeFileMenu(MenuBar mb) {

    Menu fileMenu = new Menu("File");     fileMenu.add("New");     fileMenu.add("Open...");     fileMenu.addSeparator();     fileMenu.add("Close");     fileMenu.add("Save");     fileMenu.add("Save As...");     fileMenu.addSeparator();     fileMenu.add("Page Setup...");     fileMenu.add("Print");     fileMenu.addSeparator();     fileMenu.add("Quit");     mb.add(fileMenu);

  }

}

<APPLET CODE="MenuPrimer.class"  

WIDTH=200 HEIGHT=100>

84

</APPLET>    

Događaji vezani uz menije Kad korisnik odabere opciju, meni lansira objekt tipa java.awt.event.ActionEvent. Njega može pokupiti bilo koji actionListener, dakle objekt iz klase koja implementira interface java.awt.event.ActionListener koji smo registrovali uz opciju, dakle objekt tipa MenuItem. Action komanda koju možemo pročitati metodom getActionCommand() sadržaće tekst opcije.

Na primer, sledeći applet stavlja tekst odabrane opcije u tekstualno polje theChoice.

import java.applet.*; import java.awt.*; import java.awt.event.*;  

public class ActiveMenuPrimer extends Applet implements ActionListener {

  TextField theChoice = new TextField(20);

  public void init () {

    Frame f = new Frame("Prozor i meni ");     f.add("North", new Label("Pogledajte meni ", Label.CENTER));     f.add("South", theChoice);     f.setSize(300, 200);     f.setLocation(220,240);     MenuBar myMenuBar = new MenuBar();     this.makeFileMenu(myMenuBar);     this.makeEditMenu(myMenuBar);     f.setMenuBar(myMenuBar);     f.addWindowListener(new WindowCloser());     f.show();

  }

  protected void addItem(Menu m, String s) {

    MenuItem mi = new MenuItem(s);     mi.addActionListener(this);     m.add(mi);

  }

  protected void makeEditMenu(MenuBar mb) {

85

    Menu editMenu = new Menu("Edit");     this.addItem(editMenu, "Undo");     editMenu.addSeparator();     this.addItem(editMenu, "Cut");     this.addItem(editMenu, "Copy");     this.addItem(editMenu, "Paste");     this.addItem(editMenu, "Clear");     mb.add(editMenu);

  }

  protected void makeFileMenu(MenuBar mb) {

    Menu fileMenu = new Menu("File");     this.addItem(fileMenu, "New");     this.addItem(fileMenu, "Open...");     fileMenu.addSeparator();     this.addItem(fileMenu, "Close");     this.addItem(fileMenu, "Save");     this.addItem(fileMenu, "Save As...");     fileMenu.addSeparator();     this.addItem(fileMenu, "Page Setup...");     this.addItem(fileMenu, "Print");     fileMenu.addSeparator();     this.addItem(fileMenu, "Quit");     mb.add(fileMenu);

  }  

  public void actionPerformed(ActionEvent e) {

    theChoice.setText(e.getActionCommand());

  }

  class WindowCloser extends WindowAdapter {

    public void windowClosing(WindowEvent e) {       Window w = (Window) e.getSource();       w.setVisible(false);       w.dispose();     }

  }

86

}

<APPLET CODE="ActiveMenuPrimer.class"  WIDTH=200 HEIGHT=100>

</APPLET>

Skraćenice menija Skraćenice menija, poznate i pod nazivom akceleratori ili tipovni ekvivalenti naredbe, obično ne ubrzavaju ništa, ali budući da ih korisnici vole, komercijalne aplikacije ih poseduju.

Klasa java.awt.MenuShortcut predstavlja takve skraćenice u Javi. Poseduje sledeće konstruktore:

  public MenuShortcut(int key)   public MenuShortcut(int key, boolean useShiftModifier)

U oba slučaja argument key je zapravo keycode tastera koji  aktivira tu opciju.

Ako je useShiftModifier postavljen na true, onda taster shift mora biti pritisnut da bi skraćenica aktivirala opciju. Po pretpostavci, useShiftModifier je false.

Da biste opciji izbornika pridružili skraćenicu, pozovite metodu setShortcut() iz klase java.awt.MenuItem. Na primer,     MenuShortcut pShortcut = new MenuShortcut(KeyEvent.VK_P);     MenuItem mi = new MenuItem("Print...");     mi.setShortcut(pShortcut);

Skraćenicu možete definisati i pomoću odgovarajućeg konstruktora MenuItem() ovako:  

    MenuShortcut pShortcut = new MenuShortcut(KeyEvent.VK_P);     MenuItem mi = new MenuItem("Print...", pShortcut);

Skraćenicu možete ukloniti pomoću metode deleteShortcut() iz klase java.awt.MenuItem, na primer:  

    mi.deleteShortcut();  

Padajući meniji (Popup Menus) Već smo se susreli s klasom java.awt.Choice čiji se objekti ponašaju kao padajući meniji, no imaju fiksnu lokaciju.

Klasa java.awt.PopupMenu je podklasa od java.awt.Menu. Uglavnom je koristite kao i obične menije. Stavke se dodaju metodom add(), a na korisnikove izbore odgovara se pomoću

87

ActionListenera instaliranog na MenuItem. Na primer, da biste napravili padajući meni sa različitim URL-ovima, možete postupiti ovako:

    PopupMenu pm = new PopupMenu();

    MenuItem mi = new MenuItem("http://www.javasoft.com/");     mi.addActionListener(URLActionListener);     pm.add(mi);

    mi = new MenuItem("http://home.netscape.com/");     mi.addActionListener(URLActionListener);     pm.add(mi);

    mi = new MenuItem("http://metalab.unc.edu/javafaq");     mi.addActionListener(URLActionListener);     pm.add(mi);

    mi = new MenuItem("http://www.google.com");     mi.addActionListener(URLActionListener);     pm.add(mi);

Međutim, padajući meniji ne pripadaju nekom određenom MenuBaru. Umesto toga, oni se dodaju komponenti. Na primer, za dati okvir, Frame f, instalirali biste PopupMenu pm u taj okvir tako da ga prosledite metodi add() iz klase java.awt.Component, ovako:  

    f.add(pm);

Primetite da to nije ona ista add() metoda koju koristite za dodavanje komponente okviru.

Tačan način pokretanja padajućih menija zavisi od platforme. Na primer, na Windowsima se PopupMenu pokreće podizanjem desnog tastera miša. Na Motifu se pokreće pritiskanjem desnog tastera miša. Nezavisno od sekvence događaja koja pokreće padajući meni, kad korisnik odabere neku opciju, odnosno kad odabere neki MenuItem, lansira se ActionEvent kog treba da uhvatiti odgovarajući listener registrovan uz tu stavku.

Objekt tipa PopupMenu se može ukloniti iz komponente tako da se prosledi komponentinoj metodi remove(), na primer ovako:

    f.remove(pm);

Uz jednu komponentu može biti instaliran najviše jedan padajući meni. Ako je instaliran uz kontejner, onda će trigeri iz komponenata koje se nalaze u tom kontejneru takođe pokretati padajuće menije pod uslovom da kontejner nema svoj vlastiti padajući meni.    

88

3 DIZAJN KORISNIČKOG INTERFEJSA UPOTREBOM Swing-a

Swing, koji je deo Java Foundation Class bibliteke, jeste ekstenyija Abstract Windowing Toolkit koji je integrisan u Java 1.2.

Swing pruža veću funkcionalnost nove komponente, proširene mogućnosti starih komponenti, �bolje upravljanje događajima,...

Svi elementi Swing-a su deo paketa java.awt.swing. Da bi se koristile Swing klase, mora se koristiti iskaz import sa pozivom željenih klasa ili uključiti sve klase u iskaz kao u primeru:

import java.awt.swing.*;

Swing komponente su podklase klase  JComponent.

Kostur aplikacije Pri kreiranju jednostavne Swing aplikacije, prvi koraci su kreiranje podklase klase JFrame. Klasa JFrame je proširenje klase Frame.  

  import java.awt.GridLayout;   import java.awt.event.*;   import java.awt.swing.*; :/* import javax.swing.*; */

  public class OkvirSwing extends JFrame {         public OkvirSwing() {           super("Naslov - VIDI ME");            // mesto dodavanja komponenti      }

     public static void main(String[] args) {          JFrame frame = new OkvirSwing();

         WindowListener l = new WindowAdapter() {             public void windowClosing(WindowEvent e) {                  System.exit(0);              }          };          frame.addWindowListener(l);

89

         frame.pack();          frame.setVisible(true);      }  }

Dodavanje komponenti u Swing okvir

 Pri radu sa  JFrame objektima postoke razlike u odnosu na na rad sa njegovom kopijom  AWT. Umesto da dodajete kontejnere i komponente direktno u okvir, one se moraju dodati na prelazni kontejner koji se naziva pano sadržaja-content pane.

Objekat JFrame je podeljen na nekoliko različitih panoa. Glavni pano sa kojim se radi je  content pane, koji predstavlja kompletnu oblast okvira u koji će se komponente dodavati.

Postupak dodavanja komponente u  content pane:

�  kreirati JPanel objekat (Swing verzija panela). �  dodati sve komponente (kontejnere) u JPanel upotrebom metoda add(Component). �  napraviti od panoa JPanel content pane upotrebom metoda setContentPane(Container). JPanel objekat je jedini argument.

  import java.awt.GridLayout;   import java.awt.event.*;   import java.awt.swing.*;     public class SwingDugme extends JFrame {         public SwingDugme() {           super("Naslov:  Swinger ");            String natpis = "Mozete kliknuti na mene " +              "i stupiti u interakciju sa mnom.";          JButton vDugme = new JButton(natpis);

         JPanel pane = new JPanel();          pane.add(vDugme);

         setContentPane(pane);      }

     public static void main(String[] args) {          JFrame frame = new SwingDugme();

         WindowListener l = new WindowAdapter() {              public void windowClosing(WindowEvent e) {                  System.exit(0);

90

             }          };          frame.addWindowListener(l);

         frame.pack();          frame.setVisible(true);      }  }

Rad sa Swing-om

Za svaku komponentu koja je obrađena u Abstract Windowing Toolkit-u, postoji odgovarajuća Swing komponenta.

Labele Labele su implementirane u Swing upotrebom klase JLabel. Konstruktor metodi: �  JLabel(String, int) natpis sa tekstom i poravnanjem koje je definisano jednom od tri specifikacije iz klase SwingConstants: LEFT, CENTER, RIGHT �  JLabel(String, Icon, int) natpis sa tekstom, ikonom i poravnanjem

Dugmad Za Swing dugme korisri se klasa  JButton.

Konstruktor metodi �  JButton(String) �  JButton(Icon) �  JButton(String, Icon)

Tekst polja Tekst polja su implementirana u Swing klasom  JTextField. Razlika između ovih tekst polja i njihovih  AWT parnjaka je što metod za ispis skrivenog unosa teksta, setEchoChar(char), nije podržan u klasi JTextField.

Konstruktor metodi:

�  JTextField(int) tekst polje specificirane širine. �  JTextField(String, int) tekst polje koji sadrži dati tekst i ima specificiranu širinu

Klasa JPasswordField se koristi za kreiranje tekst polja koja koriste karaktere za skrivanje unosa. Ova klasa poseduje konstruktor metode kao i JTextField: JPasswordField(int) i JPasswordField(String, int).  

Tekst oblasti Tekst oblasti su implementirane u Swing klasom JTextArea.

91

Konstruktor metodi: �  JTextArea(int, int)  tekst oblast sa navedenim brojem redova i kolona �  JTextArea(String, int, int) tekst oblast sa navedenim tekstom, brojem redova i kolona

Polja za potvrdu i radi dugmad (Check Boxes/Radio Buttons) Klasa JCheckBox je implementacija za check box-ove u Swing-u. Funkcionalnost je ista kao kod AWT sem čto sadrže i ikone kao obeležje.

Konstruktor metodi �  JCheckBox(String) check box sa navedenim tekst natpisom �  JCheckBox(String, boolean) check box sa navedenim tekst natpisom koji je aktiviran ako je drugi argument true �  JCheckBox(Icon) check box koji sadrži navedenu ikonu �  JCheckBox(Icon, boolean) check box koji sadrži navedenu ikonu i koji je aktivirana ako je drugi argument true �  JCheckBox(String, Icon) check box koji sadrži navedeni tekst i  ikonu �  JCheckBox(String, Icon, boolean) check box koji sadrži navedeni tekst i  ikonu koji su aktivirani ako treći argument je true

Check box grupe su implementirane u Swingupotrebom klase ButtonGroup.

Radio dugmad su implementirana u  Swing posredstvom klase JRadioButton. Konstruktor metode su iste kaoi u slučaju klase JCheckBox .  

Liste izbora Liste izbora koje su bile kreirane u AWT-u upotrebom klase Choice, su prisutne posredstvom klase JComboBox.

Koraci pri kreiranju 1.  Konstruktor JComboBox() se koristi bez argumenata. 2.  Metod polja za potvrdu addItem(Object) se koristi da bi se dodale stavke na listi. 3.  Metod polja za potvrdu setEditable(boolean) se koristi sa argumentom false.

Trake za pomeranke teksta - Scrollbars Scrollbarsi su  implementirane u  Swing putem klase JScrollBar.

Konstruktor metodi: �  JScrollBar(int) scrollbar sa navedenom  orientacijom. �  JScrollBar(int, int, int, int, int) scrollbar sa navedenom orientacijom, početnom vrednosti, scroll box veličinom, minimalnom vrednošću,  maximalnom vrednošću. Orijentacija je indicirana promenljivima klase SwingConstant  HORIZONTAL ili VERTICAL.

Primer prevoda apleta rgb2hsb sa prethodnog časa u aplikaciju (zapravo kostur bez metoda za upravljanje događajem koji će uskoro biti dodat)

92

 import java.awt.*; import java.awt.event.*; import javax.swing.*;

public class SwingRGB2HSB extends JFrame {     SwingColorControls RGBcontrols, HSBcontrols;     JPanel swatch;

    public SwingRGB2HSB() {         super("Konverzija");

        JPanel pane = new JPanel();         pane.setLayout(new GridLayout(1, 3, 5, 15));         swatch = new JPanel();         swatch.setBackground(Color.black);         RGBcontrols = new SwingColorControls(this, "Crvena",             "Zelena", "plava");         HSBcontrols = new SwingColorControls(this, "Hue",             "Saturation", "Brightness");         pane.add(swatch);         pane.add(RGBcontrols);         pane.add(HSBcontrols);

        setContentPane(pane);     }

    public static void main(String[] args) {         JFrame frame = new SwingRGB2HSB();

        WindowListener l = new WindowAdapter() {             public void windowClosing(WindowEvent e) {                 System.exit(0);             }         };         frame.addWindowListener(l);

        frame.pack();         frame.setVisible(true);     }

    public Insets getInsets() {         return new Insets(10, 10, 10, 10);     } }

93

class SwingColorControls extends JPanel {     SwingRGB2HSB frame;     JTextField tfield1, tfield2, tfield3;

    SwingColorControls(SwingColorTest parent,         String l1, String l2, String l3) {

        frame = parent;         setLayout(new GridLayout(3,2,10,10));         tfield1 = new JTextField("0");         tfield2 = new JTextField("0");         tfield3 = new JTextField("0");         add(new JLabel(l1, JLabel.RIGHT));         add(tfield1);         add(new JLabel(l2, JLabel.RIGHT));         add(tfield2);         add(new JLabel(l3, JLabel.RIGHT));         add(tfield3);     }

    public Insets getInsets() {         return new Insets(10, 10, 0, 0);     } }  

Mnemonici tastature

Mnemonici tastature se postavljaju metodom  setMnemonic(char) nad komponentom gde se mnemonik koristi za kontrolu.

Na primer Alt +I ce altivirati  dugme Info

JButton infoButton = new JButton("Info"); infoButton.setMnemonic('i');  

Oblačići - ToolTips

ToolTip se  kao komponente postavljaju pozivom metoda setToolTipText(String) nad ciljnom komponentom.

Primer kreiranja JScrollBar komponente i pridruživanje njenog oblačića.

JScrollBar slika = new JScrollBar(); slika.setToolTipText("Pomerite traku radi pomeranja slike");

94

Standardni dijalog boxovi Klasa JOptionPane pruža nekolikometoda za kreiranje standardnih dijalog boxova.

Postoje četiri standard dialog boksova:

�  ConfirmDialog  pitanje i  Yes, No, Cancel odgovori. �  InputDialog  upit i tekstualni unos. �  MessageDialog prikaz poruke. �  OptionDialog kombinacija prethodna tri tipa dijalog box-ova.

Confirm Dialog Boxes

Primer koji koristi ovaj tip dijalog box-a i smesta odgovor u promenljivu odgovor:

int odgovor; odgovor = JOptionPane.showConfirmDialog(null,     "Da li ste za formatiranje diska?");

Primer broj 2:

int odgovor = JOptionPane.showConfirmDialog(null,             "Da li ste za formatiranje diska?",             "Naslov u naslovnoj traci dijalog box-a",             JOptionPane.YES_NO_OPTION,             JOptionPane.ERROR_MESSAGE);

Input Dialog Boxes

Metod za kreiranje showInputDialog(Component, Object)  Argumenti su: komponenta roditelja i string/komponenta/ikona prikazani u box-u.  

String odgovor = JOptionPane.showInputDialog(null,     "Kako se zovete:");

Metod za kreiranje showInputDialog(Component, Object, String, int) Prva dva su kao u prethodnom slučaju, a ostala dva su tekst u naslovnoj traci i jedna od pet promenljivih klase koja opisuje tip dijalog boxa: ERROR_MESSAGE, INFORMATION_MESSAGE, PLAIN_MESSAGE, QUESTION_MESSAGE, ili WARNING_MESSAGE.

String odgovor = JOptionPane.showInputDialog(null,     "Unesite JMBG broj?",

95

    "Unos",     JOptionPane.QUESTION_MESSAGE);

Message Dialog Boxes

Metod za kreiranje  showMessageDialog(Component, Object)  

Za razliku od drugih dialog boxova, message dialog boxes ne vraća nikakvu korisnu vrednost kao odgovor. Primer MDB za poruke:

JOptionPane.showMessageDialog(null,     "Obrisana datoteka.");

Metod z akreiranje showMessageDialog (Component, Object, String, int) Upotreba je ista kao kod metoda showInputDialog() sa istim argumentima, sem što showMessageDialog() ne vraća vrednost.

Primer: String response = JOptionPane.showMessageDialog(null,     "Obrisana datoteka.",     " Alert no 2",     JOptionPane.WARNING_MESSAGE);

Opcioni Dijalog Boxovi

Metod za kreiranje  showOptionDialog(Component, Object, String, int, int, Icon, Object[], Object) method.

Argumenti metoda:

�  roditeljska komponenta dijaloga �  tekst, ikona, ili komponenta koja se prikazuje �  string koji se prikazuje u traci za naslov dijalog box-a �   tip dijalog boxa definisan promenljivama klase  YES_NO_OPTION, YES_NO_CANCEL_OPTION, odnosno broj 0 ukoliko ne treba niti jedno dugme �  ikona koju treba prikazati upotrebom promenljivih  ERROR_MESSAGE, INFORMATION_MESSAGE, PLAIN_MESSAGE, QUESTION_MESSAGE, WARNING_MESSAGE, odnosno broj 0 ako niti jedna od ovih ikona ne treba da bude prikazana

�  objekat Icon koji će biti prikazan umesto neke od ikona u prethodnom argumentu �  niz objekata koji sadrži komponenete odnosno druge objekte koji predstavljaju izbore u okviru dijalog boksa ukoliko se ne koriste YES_NO_OPTION i YES_NO_CANCEL_OPTION

96

objekt koji predstavlja podrazumevanu selekciju ako se ne koriste opcije YES_NO_OPTION �i YES_NO_CANCEL

Primer kreiranja opcionog dijalog box-a koji koristi niz objekata JButton za opcije u boksu i element pol[2] kao podrazumevanu selekciju:

JButton[] pol = new JButton[3]; pol[0] = new JButton("Muski"); pol[1] = new JButton("Zenski"); pol[2] = new JButton("bespolan"); int response = JOptionPane.showOptionDialog(null,     "Pol?,     "Pol dijalog",     0,     JOptionPane.INFORMATION_MESSAGE,     null,     pol,     pol[2]);

Primer koji prikazuje više dijalog boxova. Nakon prihvatanja korisnkovog unosa, one se čuvaju u tekst polja glavnog prozora.  

 1: import java.awt.GridLayout;  2: import java.awt.event.*;  3: import java.awt.swing.*;  4:  5: public class Info extends JFrame {  6:     private JLabel titleLabel = new JLabel("Title: ",  7:         SwingConstants.RIGHT);  8:     private JTextField title;  9:     private JLabel addressLabel = new JLabel("Address: ", 10:         SwingConstants.RIGHT); 11:     private JTextField address; 12:     private JLabel typeLabel = new JLabel("Type: ", 13:         SwingConstants.RIGHT); 14:     private JTextField type; 15: 16:     public Info() { 17:         super("Site Information"); 18: 19:         // naziv sajta 20:         String response1 =JOptionPane.showInputDialog(null, 21:             "Naslov sajta je:"); 22:         title = new JTextField(response1, 20); 23:

97

24:         // unos URL-a i prikaz 25:         String response2 =JOptionPane.showInputDialog(null, 26:             "URL sajta:"); 27:         address = new JTextField(response2, 20); 28: 29:         // tip sajta 30:         String[] choices = { "PrivatnoLice", "Organizacija", "Razno" }; 31:         int response3 = JOptionPane.showOptionDialog(null, 32:             "Koji je tip sajta?", 33:             "Site Type", 34:             0, 35:             JOptionPane.QUESTION_MESSAGE, 36:             null, 37:             choices, 38:             choices[0]); 39:         type = new JTextField(choices[response3], 20); 40: 41:         JPanel pane = new JPanel(); 42:         pane.setLayout(new GridLayout(3, 2)); 43:         pane.add(titleLabel); 44:         pane.add(title); 45:         pane.add(addressLabel); 46:         pane.add(address); 47:         pane.add(typeLabel); 48:         pane.add(type); 49: 50:         setContentPane(pane); 51:     } 52: 53:     public static void main(String[] args) { 54:         try { 55:             UIManager.setLookAndFeel( 56:                 UIManager.getSystemLookAndFeelClassName()); 57:         } catch (Exception e) { 58:             System.err.println("Upozorenje" 59:                              + "look and feel: " + e); 60:         } 61: 62:         JFrame frame = new Info(); 63: 64:         WindowListener l = new WindowAdapter() { 65:             public void windowClosing(WindowEvent e) { 66:                 System.exit(0); 67:             } 68:         }; 69:         frame.addWindowListener(l);

98

70: 71:         frame.pack(); 72:         frame.setVisible(true); 73:     } 74: }

99

Literatura

[1] www.wikipedia.org[2] http://download.tutoriali.org/Tutorials/JAVA/Java_za_mlade_programere.pdf[3] http://ponude.biz/knjige/tutorijali/Uvod%20u%20programske%20jezike.pdf[4] http://mago.byethost4.com/upload1/Symbian%20OS.pdf[5] http://www.link-elearning.com/dlmaterijali/materijali//DLJava/sadrzajNJpdf/JV_02sd.pdf[6] http://home.arcor.de/michal.badonsky/AJA/thesis.pdf

100