Predavanje br. index|1|2|3|4|5|6|7|8|9|10|11|12|13|14|HOME


Osmo predavanje – razmještaj komponenti

Kontrola razmještaja komponenti – razne implementacije layout managera – razmještaj tipa FlowLayout – podešavanje poravnanja za FlowLayout – razdvajanje komponenti za FlowLayout – razmještaj tipa BorderLayout – razmještaj tipa CardLayout – uporaba CardLayout razmještaja – promjena karata – razmještaj tipa GridLayout – razmještaj tipa BridBagLayout –razmještaj tipa GridBagConstraints – mreža (grid) za applet Calculator – atributi gridx i gridy – atributi gridwidth i gridheight – atribut fill – atributi ipadx i ipady – klasa Insets – atribut anchor – atributi weightx i weighty – primjer za GridLayout – ručno pozicioniranje komponenti – Kontejneri – dvije vrste kontejnera – paneli – ugnježdeni paneli – prozori (windows) – okviri (frames) – događaji vezani uz prozore – primjer događaja na prozorima – kombiniranje appleta i aplikacija – dijalozi – metode za dijaloge – primjeri dijaloga – pisanje podklasa klase Dialog


Kontrola razmještaja komponenti

Kontrolu nad pozicijama komponenti koje dodajete razmještaju omogućuje vam sučelje java.awt.LayoutManager. Budući da ne možete unaprijed znati s kako velikom površinom ćete raditi ili kakvog će ona biti oblika, kontrola će biti relativna, dakle uglavnom ćete odlučivati o tome treba li neka komponenta biti iznad ili ispod druge, poravnata lijevo ili desno, ali u pravilu nećete određivati da se komponenta treba pojaviti baš u nekoj specifičnoj točki.

Razne implementacije LayoutManagera

Sučelje java.awt.LayoutManager implementirano je u više različitih klasa, kao što su:

 

Appleti ili kontejneri imaju mogućnost koristiti ove i druge layout managere da bi odlučili gdje će staviti komponente koje u njih dodajete.

 

Klasa java.awt.FlowLayout raspoređuje komponente s lijeva na desno dok ima prostora, a tada nastavlja na isti način u retku ispod. Svaka komponenta u FlowLayout razmještaju dobija upravo onoliko prostora koliko joj minimalno treba i ništa više. Takav je razmještaj koristan za raspoređivanje buttona, ali za mnoge druge stvari nije. On je pretpostavljeni (default) razmještaj za applete i panele (posebne kontejnere o kojima će malo kasnije biti riječi).

Klasa java.awt.BorderLayout organizira applet na sekcije prema stranama svijeta: North, South, East, West i Center. North, South, East i West su pravokutnici na rubovima appleta. Oni se kontinuirano šire prema veličini komponenata u njima. Center je ono što preostane u središtu.

Klasa java.awt.CardLayout razbija applet u skupinu površina (karata) koje imaju svaka svoj vlastite razmješ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 uspoređuje sa HyperCardom na Macu ili Toolbookom on 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 dijeli applet na određeni broj redaka i stupaca te tako formira mrežu ćelija kao matricu. Kako se koja komponenta dodaje, ona se smješta u sljedeću slobodnu ćeliju, počevši od lijevog ugla prema desno i prema dolje. Svaka komponenta se podešava po veličini tako da pristaje u ćeliju. Takav razmještaj će neke komponente nepotrebno stisnuti, a neke razvući, ali je jako pogodan za razmještanje panela.

Klasa java.awt.GridBagLayout daje najprecizniji od svih AWT razmještaja. Razmješ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 smještene u ćelije počevši od gornjeg lijevog ugla niti se moraju dodavati prema desno i prema dolje.

U jednostavnim appletima sa samo nekoliko komponenti bit će dovoljan jedan razmještaj. U kompliciranijima, međutim, često ćete razbiti applet na panele, rasporediti ih prema nekom razmještaju, a onda svaki panel snabdjeti vlastitim layout managerom za raspoređivanje komponenti unutar njega.


Razmještaj tipa FlowLayout

Klasa java.awt.FlowLayout raspoređuje komponente s lijeva na desno dok ima prostora, a tada nastavlja isti postupak redak niže. Svaka komponenta dobija upravo toliko mjesta koliko joj treba i ništa više. Ovaj je tip razmještaja najkorisniji za raspoređivanje buttona.

FlowLayout je pretpostavljeni (default) razmještaj za java.awt.Panel koji je nadklasa od java.applet.Applet. Prema tome ne trebate učiniti ništa posebno da biste FlowLayout kreirali unutar appleta. Međutim, ako ga želite koristiti unutar prozora, java.awt.Window, trebat će vam odgovarajući konstruktori.

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

public FlowLayout()

Dakle, za kreiranje novog objekta tipa FlowLayout pišete:

FlowLayout fl;
fl = new FlowLayout();
 

Kao i obično, to se može skratiti na:

FlowLayout fl = new FlowLayout();

Appletu ćete reći koju specifičnu instancu klase LayoutManager želite koristiti, tako da taj objekt navedete u appletovoj metodi setLayout(). Ovu metodu klasa java.applet.Applet nasljeđ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 primjerak razmještaja direktno unutar poziva metode setLayout() ovako:

this.setLayout(new FlowLayout());


Podešavanje poravnanja za FlowLayout

Poravnanje za neki FlowLayout zadajete pomoću odgovarajućeg konstruktora. Komponente su u appletu po pretpostavci centrirane. Možete umjesto toga odrediti da budu lijevo ili desno pozicionirane. Za to možete koristiti gotove konstante FlowLayout.LEFT, FlowLayout.RIGHT ili FlowLayout.CENTER prilikom pozivanja konstruktora, npr.

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

Pogledajmo sljedeći primjer 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"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=200 HEIGHT=100>

<param name="align" value="left">

</APPLET>

 

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


Razdvajanje komponenti za FlowLayout

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

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

Na primjer, da biste napravili FlowLayout sa deset piksela horizontalnog i dvadeset piksela vertikalnog razmaka, sa lijevim poravnanjem, koristili biste sljedeći konstruktor:

FlowLayout fl =  new FlowLayout(FlowLayout.LEFT, 20, 10);
 

Pogledajte primjer appleta 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="SpaceTapeDeck.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=400 HEIGHT=100>

</APPLET>


Razmještaj tipa BorderLayout

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

 
this.setLayout(new BorderLayout());
 

U ovom tipu razmještaja nema centriranja ni lijevog ili desnog poravnavanja, no možete dodati horizontalne i vertikalne razmake među komponentama. Na primjer, 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 primjer ovako:

 
this.add(new Button("Start"), BorderLayout.SOUTH);

Kao što se iz sljedećeg primjera može vidjeti, sjeverna i južna sekcija protežu se preko appleta s lijeva na desno. Istočna i zapadna se protežu od dna sjeverne do vrha južne sekcije. Ove četiri komponente bit će onoliko velike koliko je potrebno da bi u njih stale komponente koje im dodijelite. Ono što ostane, biti će za centralnu sekciju. Točne veličine su nepredvidljive. Kao i točan način pakiranja komponenti unutar sekcija.

import java.applet.*;    
import java.awt.*;
 
public class BorderButtons 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="BorderButtons.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=200 HEIGHT=100>

</APPLET>

 


Razmještaj tipa CardLayout

Razmještaj koji implementira klasa java.awt.CardLayout je malo neuobičajen. On pretvara applet u snop karata, od kojih svaka potencijalno ima svoj vlastiti 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 razmještaj može koristiti kao niz ekrana za unos ako svi podaci ne stanu na jedan. Ili se, ako treba prikazati više podataka, može napraviti nešto kao slide show.

Na primjer, pogledajte sljedeći applet, CardTest, jedan od Sunovih standardnih demo appleta. Ovdje se koristi CardLayout za prebacivanje s jednog razmještaja na drugi, pri čemu se na različite načine raspoređuju isti buttoni:

<APPLET CODE="CardTest.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

ARCHIVE="CardTest.jar"

WIDTH=400 HEIGHT=200>

</APPLET>


Uporaba CardLayout razmještaja

Ovaj razmještaj kreirate pomoću konstruktora CardLayout() ovako:

 
    this.setLayout(new CardLayout());
 

Na raspolaganju vam je još jedan konstruktor kojim možete odrediti razmak među komponentama:

 
    this.setLayout(new CardLayout(3, 4));
 

U ovom primjeru komponente će biti 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("Pizza", new Label("How do you like your pizza?"));
this.add("Pizza", new Button("OK"));
this.add("Payment", new Label("How would you like to pay?"));
this.add("Payment", new Button("OK"));
this.add("Address", new Label("Delivery Instructions"));
this.add("Address", new Button("Order"));
 

Često se karte imenuju po brojevima:

 
this.setLayout(new CardLayout());
this.add("1", new Label("First Card"));
this.add("2", new Label("Second Card"));
this.add("3", new Label("Third Card"));
this.add("4", new Label("Fourth Card"));
this.add("5", new Label("Fifth Card"));
this.add("6", new Label("Sixth Card"));
 

Interno se popis karata i njihovih imena sprema u objekt tipa java.util.Hashtable. To znači da nema garantiranog ili ugrađenog redoslijeda karata. O tome program trebate sami voditi računa.


Promjena karata

U pravilu svakoj karti dodajete panel koji ima vlastiti LayoutManager. Svaka karta treba biti snabdjevena nekim uputnicama za navigaciju među kartama. Sam AWT nema gotovog takvog alata. Primijetite također da jednu komponentu možete dodati na više od jedne karte. To je korisno, na primjer, za kreiranje Choice izbornika sa imenima svih karata kao navigacijskim pomagalom.

Sljedećih pet metoda klase java.awt.CardLayout omogućuje promjenu aktivne karte. U svim slučajevima treba specificirati kontejner unutar kojega prelazimo s karte na kartu. To može biti applet, prozor ili panel koji je uređen u skladu s tim razmještajem.

  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)

Razmještaj tipa GridLayout

Klasa java.awt.GridLayout specificira broj redaka i stupaca u koje će komponente biti smještene. Applet se razbija na matricu jednako velikih ćelija.

GridLayout je koristan kad želite razmjestiti više objekata slične veličine. Jako je dobar za sastavljanje liste checkboxova ili radio buttona kao u appletu Ingredients iz šestog predavanja. U sljedećem primjeru donosimo malo izmijenjenu verziju tog appleta pa ćemo checkboxove rasporediti unutar šest redaka i jedne kolone, što će appletu dati mnogo bolji i uredniji izgled. Uklonjen je kod za obradu događaja jer nije bitan za ovaj primjer.

import java.applet.*;
import java.awt.*;
 
public class Ingredients2 extends Applet {
 
  TextField t;
  double price = 7.00;
 
  public void init() {
  
    this.setLayout(new GridLayout(11,1));
 
    this.add(new Label("What do you want on your pizza?", Label.CENTER));
    this.add(new Checkbox("Pepperoni"));
    this.add(new Checkbox("Olives"));
    this.add(new Checkbox("Onions"));
    this.add(new Checkbox("Sausage"));
    this.add(new Checkbox("Peppers"));
    this.add(new Checkbox("Extra Cheese"));
    this.add(new Checkbox("Ham"));
    this.add(new Checkbox("Pineapple"));
    this.add(new Checkbox("Anchovies"));
    this.t = new TextField("$" + String.valueOf(price));
    this.t.setEditable(false); 
    this.add(this.t);
  }
  
  /* ovdje dolazi kod za obradu dogadjaja 
     koji je iz ovog primjera uklonjen */
 
}
 

<APPLET CODE="Ingredients2.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=200 HEIGHT=250>

</APPLET>

 
 
 


 
 

Razmješ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đer, ovdje 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. Koristite ga ovako:

 

    GridBagLayout gbl = new GridBagLayout();

    setLayout(gbl);

Za razliku od konstruktora za GridLayout() ovaj ne kaže koliko redaka ili stupaca treba napraviti. To se određuje prema ćelijama koje vaš program referencira. Ako stavite komponentu u osmi redak i drugi stupac, Java će osigurati da bude bardevet redaka i tri stupca (retci i stupci započinju od nultog). Ako kasnije stavite komponentu u deseti redak i četvrti stupac, 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 razmještaja, referenca na objekt tipa GridBagLayout trebat će vam kasnije u programu pa ga, dakle nećete kreirati anonimno, unutar poziva metode setLayout().


Specifikacije GridBagConstraints

Svakoj komponenti koju kontrolira 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 gdje se i kako površina za prikaz smješta unutar appleta.

Konstruktor za GridBagConstraints() je trivijalan:

GridBagConstraints gbc = new GridBagConstraints();

Interakcija s objektom tipa GridBagConstraints odvija se preko jedanaest varijabli (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).

Pokazat ćemo njihovu uporabu na primjeru appleta GridBagCalculatorApplet koji predstavlja masku za kalkulator.

<APPLET CODE="GridBagCalculatorApplet.class" 
CODEBASE="http://student.math.hr/~vedris/java/classes" 
ARCHIVE="GridBagCalculator.jar" 
WIDTH=1 HEIGHT=1>
</APPLET>

Mreža (grid) za applet Calculator

Evo sada mreže koju koristimo za razmještaj kalkulatorovih komponenti. Primijetite da u mreži ima više ćelija nego komponenti kalkulatora. Kalkulator ima jedan TextField i 18 buttona različitih veličina. Neke komponente zauzet će više od jedne ćelije mreže. Na primjer, TextField koji predstavlja kalkulatorov display zauzet ć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)

(2, 5)

(3, 5)

 

Za svaku komponentu kreirat ćemo po jedan objekt tipa GridBagConstraints. Na primjer za display, equals key i zero key imat ćemo

 

    GridBagConstraints GBC_display = new GridBagConstraints();

    GridBagConstraints GBC_bigequals = new GridBagConstraints();

    GridBagConstraints GBC_0 = new GridBagConstraints();

 

Nakon što postavimo vrijednosti odgovarajućih atributa, taj ćemo objekt 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. stupac i redak ćelije u koju će doći lijevi gornji ugao komponente. Gornja lijeva ćelija u našem primjeru je ćelija (0, 0). Umjesto apsolutnih vrijednosti možemo staviti i mnemoničku konstantu GridBagConstraints.RELATIVE koja kaže da će komponenta biti smještena neposredno desno (gridx) ili neposredno ispod (gridy) u odnosu na komponentu koja je prije toga posljednja bila dodana kontejneru.

Naš kalkulator ima display u lijevom gornjem uglu appleta. Prema tome, gridx i gridy prve komponente (to je TextField) izgledat će ovako:

    GBC_display.gridx = 0;

    GBC_display.gridy = 0;

 

Isto tako, na primjer, tipka za znak jednakosti (equals key) imat će

 

    GBC_bigequals.gridx = 3;

    GBC_bigequals.gridy = 4;

 

Tipka za znamenku 0 (zero key) imat će

 

    GBC_0.gridx = 0;

    GBC_0.gridy = 5;


Atributi gridwidth i gridheight

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

Kalkulatorov display će zauzeti četiri ćelije po širini i jednu po visini, dakle imat ćemo

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

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

 

    GBC_bigequals.gridwidth = 1;

    GBC_bigequals.gridheight = 2;

 

Tipka za znamenku 0 (zero key) imat će

 

    GBC_0.gridwidth = 2;

    GBC_0.gridheight = 1;


Atribut fill

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

U našem primjeru odredili smo da se display širi horizontalno, a tipke (pogledajmo na primjer zero key) u svim smjerovima, dakle

 
    GBC_display.fill = GridBagConstraints.HORIZONTAL;

    GBC_0.fill = GridBagConstraints.BOTH;


Atributi ipadx i ipady

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

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


Atribut Insets

Atribut insets je instanca klase java.awt.Insets. On specificira razmak između komponente i rubova površine na kojoj je smještena. Za sve tipke u našem kalkulatoru odredili smo da to bude 3 piksela sa svake strane (što osigurava da susjedne tipke budu razmaknute za 6 piksela), pa imamo na primjer

 

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

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


Atribut anchor

Kad je komponenta manje nego raspoloživa površina, atribut anchor specificira položaj unutar ćelije kamo komponentu treba staviti. Mnemoničke konstante koje za to koristite slične su onima za BorderLayout. Tos u

Pretpostavljena vrijednost je GridBagConstraints.CENTER. U našem primjeru to nije eksplicitno navedeno jer su komponente dovoljno velike u odnosu na raspoložive površine, tako da je centrirana pozicija zadovoljavajuća.


Atributi 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.


Primjer za GridBagLayout

Pogledajmo sada kompletnu init() metoda sa razmještajem kalkulatorovih tipaka.

 

  public void init () {

 

    GridBagLayout gbl = new GridBagLayout();

    setLayout(gbl);

   

    // Add the display to the top four cells

    GridBagConstraints GBC_display = new GridBagConstraints();

    GBC_display.gridx = 0;

    GBC_display.gridy = 0;

    GBC_display.gridwidth = 4;

    GBC_display.gridheight = 1;

    GBC_display.fill = GridBagConstraints.HORIZONTAL;

   

    // add the text field

    TextField display = new TextField(12);

    gbl.setConstraints(display, GBC_display);

    add(display);

 

    // Add the clear button

    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);

   

    // add the button

    Button clear = new Button("C");

    gbl.setConstraints(clear, GBC_clear);

    add(clear);

 

   

    // Add the equals button   

    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);

 

    // add the = button

    Button equals = new Button("=");

    gbl.setConstraints(equals, GBC_equals);

    add(equals);

 

    // Add the / button   

    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;

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

 

    // add the button

    Button slash = new Button("/");

    gbl.setConstraints(slash, GBC_slash);

    add(slash);

 

   

    // Add the * button   

    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);

   

    // add the button

    Button star = new Button("*");

    gbl.setConstraints(star, GBC_times);

    add(star);

 

    // Add the 7 key

    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);

   

    // add the button

    Button b7 = new Button("7");

    gbl.setConstraints(b7, GBC_7);

    add(b7);

 

   

    // Add the 8 key   

    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);

 

    // add the button

    Button b8 = new Button("8");

    gbl.setConstraints(b8, GBC_8);

    add(b8);

 

    // Add the 9 key   

    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);

 

    // add the button

    Button b9 = new Button("9");

    gbl.setConstraints(b9, GBC_9);

    add(b9);

 

   

    // Add the - key   

    GridBagConstraints GBC_minus = new GridBagConstraints();

    GBC_minus.gridx = 3;

    GBC_minus.gridy = 2;

    GBC_minus.gridwidth = 1;

    GBC_minus.gridheight = 1;

    GBC_minus.fill = GridBagConstraints.BOTH;

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

   

    // add the button

    Button minus = new Button("-");

    gbl.setConstraints(minus, GBC_minus);

    add(minus);

   

    // Add the 4 key

    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);

   

    // add the button

    Button b4 = new Button("4");

    gbl.setConstraints(b4, GBC_4);

    add(b4);

 

   

    // Add the 5 key   

    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);

 

    // add the button

    Button b5 = new Button("5");

    gbl.setConstraints(b5, GBC_5);

    add(b5);

 

    // Add the 6 key   

    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);

 

    // add the button

    Button b6 = new Button("6");

    gbl.setConstraints(b6, GBC_6);

    add(b6);

 

   

    // Add the + key   

    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);

   

    // add the button

    Button plus = new Button("+");

    gbl.setConstraints(plus, GBC_plus);

    add(plus);   

 

    // Add the 1 key

    GridBagConstraints GBC_1 = new GridBagConstraints();

    GBC_1.gridx = 0;

    GBC_1.gridy = 4;

    GBC_1.gridwidth = 1;

    GBC_1.gridheight = 1;

    GBC_1.fill = GridBagConstraints.BOTH;

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

   

    // add the button

    Button b1 = new Button("1");

    gbl.setConstraints(b1, GBC_1);

    add(b1);

 

   

    // Add the 2 key   

    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);

 

    // add the button

    Button b2 = new Button("2");

    gbl.setConstraints(b2, GBC_2);

    add(b2);

 

    // Add the 3 key   

    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);

 

    // add the button

    Button b3 = new Button("3");

    gbl.setConstraints(b3, GBC_3);

    add(b3);

 

   

    // Add the = key   

    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);

   

    // add the button

    Button bigequals = new Button("=");

    gbl.setConstraints(bigequals, GBC_bigequals);

    add(bigequals);

   

    // Add the 0 key

    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);

   

    // add the button

    Button b0 = new Button("0");

    gbl.setConstraints(b0, GBC_0);

    add(b0);

 

   

    // Add the . key   

    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;

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

 

    // add the button

    Button bdecimal = new Button(".");

    gbl.setConstraints(bdecimal, GBC_decimal);

    add(bdecimal);

 

  }


Ručno pozicioniranje komponenti

Komponente je moguće postaviti na točno određenu poziciju na ekranu, koristeći koordinate u pikselima, u odnosu na appletov panel. To, međutim, ima više nedostataka.

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 (rekli smo 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)
 

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

Sljedeći applet stavit će button veličine 30 x 40 piksela (tj. njegov lijevi gornji ugao) u točku (25, 50):

import java.applet.*;
import java.awt.*;
 
public class ManualLayout extends Applet {
 
  private boolean laidOut = false;
  private Button myButton;
 
  public void init() {
 
    this.setLayout(null);
    this.myButton = new Button("OK");
    this.add(this.myButton);
  }
 
   public void paint(Graphics g) {
     if (!this.laidOut) {
        this.myButton.setLocation(25, 50);
        this.myButton.setSize(30, 40);
        this.laidOut = true;
     }
   }
 
}
 

<APPLET CODE="ManualLayout.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=100 HEIGHT=100>

</APPLET>


Što je Container?

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

Općenito, komponente se nalaze u nekom kontejneru. Applet je primjer kontejnera, no to mogu biti i prozori (windows), okviri (frames), dijalozi (dialogs) i paneli (panels). Kontejneri mogu sadržavati druge kontejnere.

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

Ukratko, kontejneri sadrže komponente. Komponente su pozicionirane unutar kontejnera u skladu sa pridruženim Layout managerom. Budući da su kontejneri također komponente, oni se mogu naći unutar drugih kontejnera. Primijetimo da appleti osiguravaju već gotov kontejner i pretpostavljeni Layout manager. To je FlowLayout.


Dvije vrste Containera

Paket AWT definira više vrsta kontejnera među kojime ćemo promotriti panele i prozore.

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

Prozori su podklase od java.awt.Window. Prozor je samostalan. Ima ih više vrsta, među njima promatrat ćemo okvire (frames) i dijaloge (dialogs). Okviri su podklase od java.awt.Frame. Predstavljaju obične, prirodne prozore. Dialozi su podklase od java.awt.Dialog. Dialog je privremeni, nestalni prozor koji postoji samo da prenese neke informacije ili primi neki input od korisnika.


Paneli

Svaki Panel je zapravo generički Container čija je glavna uloga podijeliti prikaznu površinu u odvojene pravokutne dijelove. Budući da svaki Panel može imati svoj vlastiti LayoutManager, s panelima možete učiniti mnogo toga što inače ne biste mogli sa samo jednim Layout managerom.

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

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

Umjesto toga, možete kreirati applet koji ima BorderLayout, a TextArea mu se nalazi u centru. Zatim kreirate Panel, postavite njegov LayoutManager na FlowLayout, dodate button tom panelu i onda dodate panel južnom dijelu appleta. Pogledajte program:

 
import java.applet.*;
import java.awt.*;
 
 
public class PanelExample 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);
    
  }
 
}
 

<APPLET CODE="PanelExample.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=300 HEIGHT=200>

</APPLET>

 

U ovom je primjeru važno razlikovati dodavanje komponente appletu (add(...) ili this.add(...)) od dodavanja komponente panelu (p.add(...)).

S druge strane, nije važno jeste li prvo dodali panel appletu pa onda button panelu ili obrnuto.

Druga česta uporaba panela je za postavljanje niza checkboxova koji imaju GridLayout s jednim stupcem.


Ugniježdeni paneli

Ponekad je potrebno nekoliko instanci istog LayoutManagera. Pogledajmo opet primjer kalkulatora.

S jedne strane izgleda kao da ga je jednostavno implementirati. Tu su naprosto 18 buttona i TextField. S druge strane, gotovo sve tipke su jednake veličine, samo su dvije tipke i display nešto veći. Gotovo bi se mogao koristiti GridLayout, ali ipak ne sasvim. Paneli su jedan od načina rješavanja ovog problema.

Evo sada ponovno kalkulatora, ali ovog puta smo koristili samo GridLayout i ugniježdene panele. Da li je to jednostavnije nego GridBagLayout ili nije, stvar je ukusa.

 
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);
 
    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);
  
  }
 
  /* Use 1.0 event handling since I need to run this
     inside today's web browsers. */
  public boolean action(Event e, Object arg) {
    if (e.target instanceof Button) {
      screen.setText((String) arg);
      return true;
    }
    return false;
  
  }
 
}
 

<APPLET CODE="Calculator.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=150 HEIGHT=150>

</APPLET>


Prozori (windows)

Klasa java.awt.Window i njene podklase omogućuju vam kreiranje samostalnih prozora. Samostalni prozori su česti u aplikacijama koje koje za komunikaciju s korisnikom koriste AWT umjesto komandne linije. Također 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.

Uobičajeno je da se klasa java.awt.Window ne koristi direktno. Umjesto toga radite s njenim podklasama, npr. java.awt.Frame ili java.awt.Dialog, ovisno o tome što trebate. Frame je okvir koji može imati svoj scrollbar, korisnik mu može mijenjati veličinu ili položaj i bit će na ekranu dok god korisnika zanima njegov sadržaj.

Nasuprot tome, dijalog neće imati izbornike, obično mu se ne može mijenjati veličina iako se može pomicati. Njegova je uloga prenošenje određene informacije (unosa) od korisnika ili pak upozoravanje na nešto. 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 vam odvajanje različitih funkcija ili podataka u različite prozore. Na primjer, 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 vam treba za kreiranje okvira i rad s njima nalazi se u klasi java.awt.Frame. Za kreiranje novog okvira bez naslovne letvice koristit ćete konstruktor Frame() bez argumenata.

Frame f = new Frame();
 

Češće će ipak biti potrebno dati okviru naslov:

 
Frame f = new Frame("My Window");
 

Okviri nasljeđuju klasu java.awt.Container pa im dakle možete dodavati komponente. Za razliku od panela i appleta, pretpostavljeni LayoutManager za okvire je BorderLayout, a ne FlowLayout. To, naravno, možete promijeniti pomoću metode setLayout() na primjer ovako:

 
f.setLayout(new FlowLayout());
 

Okviri nasljeđuju i klasu java.awt.Component pa dakle imaju metode paint() i update(). Ako želite crtati unutar okvira i procesirati događaje ručno kao u appletima, jednostavno kreirajte podklasu od Frame i dodajte joj odgovarajući listener. Gotovo sve što ste radili sa vlastitim podklasama od java.awt.Applet možete također raditi i sa svojim podklasama od java.awt.Frame.

Ipak, najčešće ćete htjeti koristiti komponente. Da bist komponentu dodali okviru, pozvat ćete njegovu metodu  add() isto kao što st pozivali appletovu metodu  add(). Jedina razlika je što ćete često trebati pozivati tu metodu izvan klase Frame, tako da će biti potrebno dodati odgovarajući prefiks koji pokazuje na okvir. Drugim riječima, ako imate okvir Frame f, trebat ćete pozvati

f.add(new Button("OK");
 

umjesto samo

 
this.add(new Button("OK"));
 

Naravno, to ovisi u kojoj ste klasi kad pozivate add(). Ako je pozivate iz neke od podklasa klase Frame, onda to neće biti potrebno.

Kako je pretpostavljeni layout za frame BorderLayout, trebat će specificirati da li komponentu dodajete na North, South, East, West ili Center. Evo primjera koji pokazuje kako se dodaje centrirana labela u centar okvira Frame f:

f.add("Center", new Label("This is a frame", Label.CENTER));
 

Ili

f.add(new Label("This is a frame", Label.CENTER), BorderLayout.CENTER);
 

Veličina i pozicija bilo kojeg danog okvira je nepredvidljiva ako je ne specificirate. Veličina se zadaje pomoću metode setSize() ovako:

 
f.setSize(150,150);
 

Ta veličina ne uključuje naslovnu letvicu, pa to treba zasebno uzeti u obzir. Da biste doznali visinu naslovne letvice za okvir, pozvat ćete njegovu metodu insets() i pogledati atribut top rezultirajućeg objekta iz java.awt.Insets. To će biti visina naslovne letvice. Imat ćemo, dakle

 
int TitleBarHeight = 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 ustabili. Kad ste završili s dodavanjem komponenti, učinite okvir vidljivim tako da pozovete njegovu metodu 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:

Da biste mogli odgovarati na te događaje, morate uz objekt tipa java.awt.Window registrirati odgovarajući listener, dakle objekt neke klase koja implementira sučelje java.awt.event.WindowListener. Ovo sučelje propisuje sljedeć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)
  public abstract void windowActivated(WindowEvent e)
  public abstract void windowDeactivated(WindowEvent e)

 

Možete, naravno, koristiti i odgovarajući java.awt.event.WindowAdapter.


Primjer događaja na prozorima

Na primjer, prozori se ne zatvaraju sami od sebe nego ih morate eksplicitno zatvoriti. Sljedeća podklasa od Frame koja odgovara na pokušaj zatvaranja tako da pozove metode setVisible(false) i dispose().

 
import java.awt.*;
import java.awt.event.*;
 
 
public class ClosableFrame extends Frame implements WindowListener {
 
  public ClosableFrame() {
    this.addWindowListener(this);
  }
  
  public ClosableFrame(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žete je aktivirati na primjer pomoću sljedećeg appleta:

 

import java.applet.Applet;

import java.awt.*;

 

 

public class ClosableFrameApplet extends Applet {

 

  public void init() {

 

    ClosableFrame cf = new ClosableFrame();

    cf.setSize(150,150);

    cf.setLocation(100,100);

    cf.show();

 

  }

 

}

 

<APPLET CODE="ClosableFrameApplet.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

ARCHIVE="ClosableFrame.jar"

WIDTH=200 HEIGHT=100>

</APPLET>


Kombiniranje appleta i aplikacija

Appletu je potreban okvir da bi se izvršavao. U pravilu web browser osigurava takav okvir. No možete kreirati instance svog appleta unutar nekog okvira vaše vlastite aplikacije. Na taj način možete pisati kod koji je istovremeno i applet i aplikacija.

Da bi applet pretvorili u aplikaciju, dodajte mu sljedeću main() metodu (ovdje je myApplet ime vašeg appleta):

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

Redak 1 je deklaracija standardne main() metoda koju koristite za aplikacije s komandne linije. Ako se applet izvršava unutar web browsera ili applet viewera, ta će metoda biti ignorirana. Izvršit će se samo ako applet pokrenete kao samostalni program.

Redak 3 kreira instancu vašeg appleta. Tu trebate umjesto myApplet upisati pravo ime svog appleta.

Nakon toga, retci 4 i 5 pozivaju appletovu init() i start() metodu. To inače radi web browser za vas, ali ako se program izvršava samostalno, morate to sami učiniti.

Nakon što ste kreirali aplet, treba vam Frame u koji ćete ga smjestiti. Redak 7 to čini pomoću uobičajenog konstruktora Frame(). Ovdje možete promijeniti naslov okvira da odgovara vašoj aplikaciji.

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

Redak 9 zadaje veličinu za Frame. Ovdje smo stavili 150 x 150 pixela. Ako se program izvršava kao applet, možete dobiti te vrijednosti iz parametara width i height, ali ako se izvršava samostalno, morate izmisliti neke veličine. Možete ih eventualno učitati kao argumente s komandne linije.

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

Redak 11 čini vaš 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 konvertirate applet u aplikaciju na opisani način, morate osigurati da se program ne oslanja na metode koje imaju smisla jedino u appletima. Na primjer, 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 iznimaka (java.lang.SecurityException).

Pogledajte kako to funkcionira na primjeru appleta Dots iz sedmog predavanja koji smo za ovu svrhu modificirali u applet/aplikaciju DotsTest.


Dijalozi

Okviri su korisni kao prozori koji će se neko vrijeme zadržati na ekranu, na primjer u svrhu editiranja 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 pomicati, mijenjati im veličinu i dodavati im komponente skoro isto kao i u slučaju okvira. Postoje, međutim, dvije bitne razlike:

  1. Okvir (frame) može imati letvicu izbornika (menu bar) dok dijalog to ne može
  2. Dijalog može biti modalan, dok okvir ne može

O izbornicima ćete naučiti u sljedećem predavanju. Za sada se zadržimo na razlici između modalnih i ne-modalnih dijaloga. Modalni dijalog blokira komunikaciju sa svim drugim aplikacijama sve dok ne dobije odgovarajući input od korisnika. Ne može se pomicati i ne dozvoljava korisniku prijelaz u drugi prozor istog programa. Na nekim platformama ne dozvoljava čak i odlazak u prozore drugih programa.

Sedamdesetih godina proširio se virus koji bi periodički prekidao korisnikov rad podizanjem prozorčića na kojem je pisalo "I WANT A COOKIE." Rad se mogao nastaviti tek kad bi korisnik upisao riječ "COOKIE" na što bi program rekao nešto kao "MMM, MMM, THAT WAS GOOD." i tek tada vratio kontrolu korisniku.

Modalni dijalozi se ponašaju prilično slično tom virusu. Oni traže input od korisnika i ne dozvoljavaju da se išta dogodi dok ga ne dobiju. Ne-modalni dijalozi se podižu, ali ne sprečavaju korisnika da radi druge stvari dok su oni vidljivi. Budući da modalni dijalozi djeluju ponešto iritirajuće, treba ih u pravilu izbjegavati.


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, na primjer, staviti:

 
Dialog d = new Dialog(new Frame(), false);
 

Prvi argument je parent 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 parent frame, dakle privremeno sprečavaju unos u taj okvir, ali ne i u druge okvire.

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

Ako kreirate parent frame direktno unutar poziva konstruktora kao u prethodnom primjeru, dijalog ne može biti uistinu modalan.

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

  1. Korisnik može mijenjati položaj i veličinu većini okvira, dok dijalozima u pravilu ne može.
  2. Okviri obično imaju naslovne letvice, dok okviri nemaju.

Dijalogu možete omogućiti promjenjivost veličine pomoću metode setResizable():

 
d.setResizable(true);
 

Možete mu dati naslovnu letvicu tako da ga kreirate pomoću sljedećeg konstruktora::

 
Dialog d = new Dialog(new Frame(), "My Dialog Window", false);
 

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


Primjeri dijaloga

Sljedeći program prikazuje jednostavni ne-modalni dijalog sa OK buttonom i bez naslovne letvice.

 
import java.applet.*;
import java.awt.*; 
 
public class DialogTester extends Applet {
 
  public void init() {
    
    Dialog myDialog = new Dialog(new Frame(), false);
    myDialog.setLocation(320,240);
    myDialog.add("North", new Label("Hello!"));
    myDialog.add("South", new Button("OK"));
    myDialog.pack();
    myDialog.show();
    
  }
  
}
 

<APPLET CODE="DialogTester.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

WIDTH=150 HEIGHT=150>

</APPLET>


Pisanje podklasa klase Dialog

Prethodni primjer je bio malo umjetan. U pravilu, kreirat ćete svoje vlastite podklase od java.awt.Dialog i i instancirati ih iz glavnog programa. Na primjer, jedan od jednostavnijih uobičajenih dijaloga je ispis poruke koju korisnik treba pročitati i potvrditi to pritiskom na OK button. Evo primjera:

 

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);

    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 AlertExample extends Applet {

 

  public void init () {

 

    Dialog d = new YesNoDialog(new Frame(),

     "Are you sure you want to start global thermonuclear war?");

    d.show();

   

  }

 

}

 

<APPLET CODE="AlertExample.class"

CODEBASE="http://student.math.hr/~vedris/java/classes"

ARCHIVE="AlertExample.jar"

WIDTH=300 HEIGHT=200>

</APPLET>