Predavanje br. index|1|2|3|4|5|6|7|8|9|10|11|12|13|14|HOME
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
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.
Sučelje java.awt.LayoutManager
implementirano je u više različitih klasa, kao što su:
java.awt.FlowLayout
java.awt.BorderLayout
java.awt.CardLayout
java.awt.GridLayout
java.awt.GridBagLayout
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.
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());
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.
Većina
LayoutManager
a
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>
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
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>
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.
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)
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>
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()
.
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>
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
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
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
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:
GridBagConstraints.NONE
:
komponenta ne mijenja veličinu
GridBagConstraints.HORIZONTAL
:
Komponenta će se protezati preko cijele širine prostora koji joj je
dodijeljen, ali neće promijeniti svoju visinu
GridBagConstraints.VERTICAL
:
Komponenta će se protezati preko cijele visine prostora koji joj je
dodijeljen, ali neće promjijeniti svoju širinu
GridBagConstraints.BOTH
:
Širina i visina komponente bit će prilagođene tako da komponenta zauzme cijeli
prostor koji joj je dodijeljen 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;
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
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);
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
GridBagConstraints.CENTER
GridBagConstraints.NORTH
GridBagConstraints.NORTHEAST
GridBagConstraints.EAST
GridBagConstraints.SOUTHEAST
GridBagConstraints.SOUTH
GridBagConstraints.SOUTHWEST
GridBagConstraints.WEST
GridBagConstraints.NORTHWEST
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.
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.
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);
}
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.
GridBagLayout
u kombinaciji sa ugnijež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 (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>
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
.
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.
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.
Ponekad
je potrebno nekoliko instanci istog LayoutManager
a.
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>
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
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();
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
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.
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>
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.
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:
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.
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.:
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.
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>
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>