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


Šesto predavanje - komponente

Što su komponente? – labele – tri koraka u dodavanju komponente – gdje je metoda paint()? – metode klase Label – buttoni – akcije na buttonima – primjer appleta sa akcijom na buttonu – različiti obrasci za događaje – višestruki ActionListeneri – metode za buttone – Action naredbe – više buttona u istom appletu – unutarnje klase kao EventListeneri – tekstualna polja – primjer tekstualnih polja u Javi – TextArea – klasa TextComponent – sučelje TextListener i klasa TextEvent – klasa Canvas – klasa Choice – metode klase Choice – klasa ItemListener – klasa Checkbox – događaji iz klase Checkbox – klasa CheckboxGroup – primjer CheckboxGroup – klasa List – metode klase List – događaji klase List – klasa Scrollbar


Što su komponente?

Komponente su sastavnice grafičkog korisničkog sučelja (GUI, graphical user interface).

U Javi, komponente su podklase od java.awt.Component, a najčešće korištene su:

Sve komponente se iscrtavaju samostalno (bez pisanja posebne paint() metode.


Labele

Najjednostavnija komponenta je java.awt.Label. U sljedećem primjeru je Label l redak teksta koji je read-only.

 
import java.applet.*;
 import java.awt.*;
 
 public class HelloContainer extends Applet {
 
   public void init() {
     Label l;
     l = new Label("Hello Container");
     this.add(l);
   }
 
 }
 

<APPLET CODE="HelloContainer.class"

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

WIDTH=100 HEIGHT=100>

</APPLET>

 

Kao i obično, program započinjete importiranjem potrebnih klasa. U ovom slučaju to su java.applet.Applet i java.awt.Label.

Naša klasa će imati samo jednu metodu, init(). Ona će obaviti tri stvari. Deklarirat će da je l labela, instancirati je pomoću konstruktora Label(String s) i dodati je razmještaju (layout). Općenito, to se ne mora obaviti uvijek unutar metode init(), ali najčešća praksa je upravo takva.


Tri koraka u dodavanju komponente

  public void init() {
     Label l;
     l = new Label("Hello Container");
     this.add(l);
   }
 

Ključna stvar koju valja zapamtiti o dodavanju komponenti appletu su sljedeća tri koraka:

  1. Deklarirati komponentu
  2. Inicijalizirati komponentu
  3. Dodati komponentu razmještaju (layout)

Prva dva koraka moraju se obaviti prilikom kreiranja instance bilo koje klase, tako da nam samo treći korak predstavlja novost.

Možete to napraviti, naravno, i u jednoj naredbi, na primjer ovako:

this.add(new Label("Hello Container"));

Nedostatak ovog kraćeg zapisa je taj što se izgubila referenca na labelu (varijabla l). Ipak, labele se u pravilu ne mijenjaju, tako da uglavnom nije posebna smetnja.


Gdje je metoda paint()

Primijetite da u našem appletu nema paint(), a tekst se svejedno ispisuje na ekranu. Komponente se, naime, same iscrtavaju. Svaki put kad se container kao što je applet ponovno iscrta, on pozove ne samo svoju vlastitu paint() metodu, nego i paint() metode svih svojih komponenti. Klasa java.awt.Label ima svoju vlastitu paint() metodu koja zna kako se treba iscrtati. O iscrtavanju komponenti ne morate voditi računa dok god ne kreirate vlastite klase komponenata ili izmijenite izgled sistemskih komponenata.


Metode klase Label

Labele su jednostavni objekti koji imaju tek nekoliko konstruktora i vlastitih, ako se izuzmu one koje su naslijeđene od java.awt.Component (kojoj je java.awt.Label podklasa).

 
  public final static int LEFT
  public final static int CENTER
  public final static int RIGHT
 
  public Label()
  public Label(String text)
  public Label(String text, int alignment)
 
  public void addNotify()
  public int getAlignment()
  public synchronized void setAlignment(int alignment)
  public String getText()
  public synchronized void setText(String text) 
 

Već smo vidjeli osnovni konstruktor za labele. Možete također kreirati labelu koristeći konstruktor Label() bez argumenata, no to općenito nema smisla. Nadalje, možete odrediti da tekst bude poravnat lijevo, desno ili centrirano, za što vam stoji na raspolaganju odgovarajući konstruktor:

 
Label center = new Label("Ova labela je centrirana", Label.CENTER);
Label left = new Label("Ova labela je lijevo poravnata", Label.LEFT);
Label right = new Label("Ova labela je desno poravnata", Label.RIGHT);
 

Dvije su metode iz java.awt.Label koje će povremeno biti potrebne, a to su getText() i setText(String s). One dozvoljavaju da doznate i promijenite tekst labele dok se applet izvršava. Na primjer,

 
String s = l.getText();
l.setText("Ovo je nova labela");

Buttoni

Buttoni su instance klase java.awt.Button koja je podklasa od java.awt.Component. Buttoni se kreiraju pomoću konstruktora Button(String label). On će kreirati novi button sa labelom koja će na njemu biti ispisana. Kad ga kreirate, možete ga dodati razmještaju. Na primjer,

 
    Button b; 
    b = new Button("My First Button");
    this.add(b);
 

Sintaksa je gotovo identična kao za labele i vidjet ćete da je takva i za ostale komponente grafičkog sučelja. Jedino što se mijenja su konstruktori.

Kraći oblik je također isti:

add(new Button("My First Button"));

Evo jednog appleta koji sadrži button:

import java.applet.*;
import java.awt.*;
 
 
public class FirstButton extends Applet {
  
   public void init () {
   
     this.add(new Button("Moj prvi Button"));
   
   }
 
}
 

<APPLET CODE="HelloContainer.class"

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

WIDTH=100 HEIGHT=100>

</APPLET>


Akcije na buttonima

Za razliku od labela, buttoni čine nešto kad kliknete na njih. Kad miš klikne na neki objekt tipa Button, onda će on ispaliti objekt tipa ActionEvent. Da biste bili spremni odgovoriti na taj događaj, potrebno je buttonu pridružiti i odgovarajući ActionListener. Na primjer,

 
     Button beep = new Button("Beep");    
     add(beep);  // dodajemo buttom razmjestaju
     beep.addActionListener(myActionListener); // pridruzujemo buttonu action listener
 

Ovdje je myActionListener referenca na objekt koji implementira sučelje (interface) java.awt.event.ActionListener. To sučelje propisuje samo jednu metodu:

public abstract void actionPerformed(ActionEvent e)

Objekt tipa ActionListener učinit će nešto s rezultatom, objektom tipa ActionEvent kojeg je ispalio button nakon što je zabilježio klik mišem. Na primjer, sljedeća klasa će, kad dobije ActionEvent, proizvesti beep signal:

import java.awt.*;
import java.awt.event.*;
 
public class BeepAction implements ActionListener {
 
  public void actionPerformed(ActionEvent e) {
 
    Toolkit.getDefaultToolkit().beep();
 
  }
 
}

Primjer appleta sa akcijom na buttonu

Sljedeći applet ima button označen labelom na kojoj piše "Beep". Button je na uobičajeni način dodan razmještaju, a metoda addActionListener() propisuje da će na buttonove ActionEvente reagirati odgovarajući ActionListener, u ovom slučaju objekt klase BeepAction.

You will only see somethinghere if your browser supports Java 1.1.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class BeepApplet extends Applet {
  
   public void init () {
   
     // Konstruiramo button
     Button beep = new Button("Beep");
 
     // dodajemo button razmjestaju
     this.add(beep);
 
     // propisujemo da ce action evente koje ovaj button posalje
     // obraditi novi objekt klase BeepAction
     beep.addActionListener(new BeepAction());
   
   }
 
}
 

<APPLET CODE="BeepApplet.class"

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

ARCHIVE="Beep.jar"

WIDTH=100 HEIGHT=100>

</APPLET>


Različiti obrasci za događaje

Glavna je prednost Javinog modela događaja je da se GUI može odvojiti od ostalog koda. Kako je ActionListener sučelje (interface), a ne klasa, on može biti implementiran gdje god nam odgovara. Na primjer, applet može i sam obrađivati svoje događaje, što ćemo vidjeti iz sljedećeg primjera:

 
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class BeepApplet extends Applet implements ActionListener {
  
   public void init () {
   
     // Construct the button
     Button beep = new Button("Beep");
 
     // add the button to the layout
     this.add(beep);
 
     // specify that action events sent by this
     // button should be handled by the applet itself
     beep.addActionListener(this);
   
   }
 
  public void actionPerformed(ActionEvent e) {
 
    Toolkit.getDefaultToolkit().beep();
 
  }
 
}
 

<APPLET CODE="BeepApplet.class"

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

WIDTH=100 HEIGHT=100>

</APPLET>


Višestruki ActionListeneri

Primijetite da niste ograničeni na samo jedan listener po događaju. Na primjer, sljedeći program generira pet beep-ova svaki put kad pritisnete button.

 
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class BeepFiveApplet extends Applet  {
  
   public void init () {
   
     // Construct the button
     Button beep = new Button("Beep");
 
     // add the button to the layout
     this.add(beep);
 
     // specify that action events sent by this
     // button should be handled by a new BeepAction object
     beep.addActionListener(new BeepAction());
     beep.addActionListener(new BeepAction());
     beep.addActionListener(new BeepAction());
     beep.addActionListener(new BeepAction());
     beep.addActionListener(new BeepAction());
   
   }
 
}
 

<APPLET CODE="BeepFiveApplet.class"

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

ARCHIVE="BeepFive.jar"

WIDTH=100 HEIGHT=100>

</APPLET>

 

Kad pritisnete button, on će lansirati ActionEvent, a svaki od pet objekata klase BeepAction dobit će kopiju tog događaja. Redosljed primanja tih kopija nije specificiran.

 

Ako je vaše računalo prebrzo da biste čuli svih pet beep-ova, dodajte unutar metode ActionPerformed() iz klase BeepAction još i naredbu

 
System.out.println("Beep"); 
 

Pogledate li applet pomoću appletviewera, moći ćete pratiti ispis svaki put kad pritisnete button i vidjeti da se akcija zaista događa pet puta.


Metode za buttone

Buttoni su jednostavni objekti. Uglavnom sve što trebate napraviti s njima je dodati ih u razmještaj i pridružiti im ActionListener. Na raspolaganju su vam i sljedeće metode:

 
public void addNotify()
public String getLabel()
public synchronized void setLabel(String label)
public void setActionCommand(String command)
public String getActionCommand()
public void addActionListener(ActionListener l)
public void removeActionListener(ActionListener l)
 

addNotify() kreira takozvani  peer objekt za zadani button, tj. native masku koja izgleda kao Windows button ili Mac button ili Motif button, no ona se rijetko direktno poziva.

Metode getLabel() i setLabel(String s) omogućuju dohvaćanje i mijenjanje teksta koji se pojavljuje na buttonu za vrijeme izvršavanja appleta. Na primjer, za neki Button b, možemo imati:

String s = b.getLabel();
b.setLabel("Here's the new label");
 

Primijetite da metoda unatoč sugestivnom imenu getLabel() vraća objekt tipa String, a ne Label.

Metode setActionCommand() i getActionCommand() modificiraju komandni string koji sa sobom nosi ActionEvent. Po pretpostavci to je labela buttona, ali to se može promijeniti. Na primjer, možete zadati broj ponvljanja beep signala koji će applet proizvesti na klik mišem (pogledajte BeepFiveApplet).

Metoda addActionListener() registrira neki objekt kao onaj koji bi trebao primiti ActionEvent koji će Button ispaliti. Metoda removeActionListener() poništava tu registraciju, tako da objekt tipa ActionListener više neće primati ActionEvente koje button ispali.


Action naredbe

Metode setActionCommand() i getActionCommand() modificiraju komandni string koji putuje uz ActionEvent. Po pretpostavci, to je labela buttona, ali to se može promijeniti. Na primjer, možete na taj način proslijediti broj ponaljanja beep signala koje applet treba proizvesti.

 
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class BeepFiveApplet extends Applet  {
  
   public void init () {
   
     // Construct the button
     Button beep = new Button("Beep");
 
     // add the button to the layout
     this.add(beep);
 
     // specify that action events sent by this
     // button should be handled by the applet itself
     beep.addActionListener(new MultiBeepAction());
     beep.setActionCommand("5");
   
   }
   
}
 
class MultiBeepAction implements ActionListener {
 
  public void actionPerformed(ActionEvent ae) {
 
    int n;
    try {
      n = Integer.parseInt(ae.getActionCommand());
    }
    catch (NumberFormatException e) {
      n = 1;
    }
    Toolkit tk = Toolkit.getDefaultToolkit();
    for (int i = 0; i < n; i++) tk.beep();
 
  }
 
}
 

<APPLET CODE="BeepFiveApplet.class"

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

ARCHIVE="MultiBeep.jar"

WIDTH=200 HEIGHT=200>

</APPLET>


Više buttona u istom appletu

Naravno, moguće je imati više od jednog buttona u appletu. Svaki button koji će izazvati neku akciju mora registrirati bar jedan objekt koji je ActionListener. Različiti buttoni mogu registrirati različite ActionListenere , ali ih mogu i dijeliti. ActionListeneri za buttone mogu pripadati istoj klasi, ali ne moraju. Ako dva buttona registriraju isti ActionListener, uobičajeno je koristiti action komandu da bismo razlikovali akcije.

 
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class TwoButtons extends Applet  {
  
   public void init() {
   
     MultiBeepAction mba = new MultiBeepAction();
 
     // Construct the button
     Button beep = new Button("Beep Once");
 
     // add the button to the layout
     this.add(beep);
 
     beep.addActionListener(mba);
     beep.setActionCommand("1");
     
     Button beepTwice = new Button("Beep Twice");
     beepTwice.addActionListener(mba);
     beepTwice.setActionCommand("2");
     this.add(beepTwice);
     
   }
   
}
 
class MultiBeepAction implements ActionListener {
 
  public void actionPerformed(ActionEvent ae) {
 
    int n;
    try {
      n = Integer.parseInt(ae.getActionCommand());
    }
    catch (NumberFormatException e) {
      n = 1;
    }
    Toolkit tk = Toolkit.getDefaultToolkit();
    for (int i = 0; i < n; i++) tk.beep();
 
  }
 
}
 

<APPLET CODE="TwoButtons.class"

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

ARCHIVE="TwoButtons.jar"

WIDTH=200 HEIGHT=100>

</APPLET>


Unutarnje klase kao Event Listeneri

Uobičajeno je da klasa koja realizira event listener bude unutarnja klasa. To se najčešće primjenjuje na prilagođene podklase komponenata koje žele same obrađivati svoje događaje.

 
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class TwoButtons extends Applet  {
  
   public void init() {
   
     MultiBeepAction mba = new MultiBeepAction();
 
     // Construct the button
     Button beep = new Button("Beep Once");
 
     // add the button to the layout
     this.add(beep);
 
     // specify that action events sent by this
     // button should be handled by the MultiBeepAction mba
     beep.addActionListener(mba);
     beep.setActionCommand("1");
     
     Button beepTwice = new Button("Beep Twice");
     beepTwice.addActionListener(mba);
     beepTwice.setActionCommand("2");
     this.add(beepTwice);
     
   }
 
  class MultiBeepAction implements ActionListener {
 
    public void actionPerformed(ActionEvent ae) {
 
      int n;
      try {
        n = Integer.parseInt(ae.getActionCommand());
      }
      catch (NumberFormatException e) {
        n = 1;
      }
      Toolkit tk = Toolkit.getDefaultToolkit();
      for (int i = 0; i < n; i++) tk.beep();
 
    }
  }
}
 

<APPLET CODE="TwoButtons.class"

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

ARCHIVE="TwoButtonsIC.jar"

WIDTH=200 HEIGHT=100>

</APPLET>


Tekstualna polja

Klasa java.awt.TextField omogućuje ugradnju maske za unos i editiranje jedne linije teksta. Korisna je za jednostavne operacije unosa malih količina podataka. Ima četiri konstruktora:

  public TextField()
  public TextField(String text)
  public TextField(int num_chars)
  public TextField(String text, int num_chars)
 

Zbog načina na koji Java razmješta tekst, konstruktor bez argumenata bi valjalo izbjegavati. Koristite ili onaj koji ima String ili zadajte broj znakova koje će ta kućica sadržavati. Na primjer,

 
TextField name = new TextField("Type your name here");
TextField socialSecurity = new TextField(11);
 

Kad korisnik pritisne tipku return ili enter unutar TextFielda, ispali se jedan ActionEvent. Možete ga uloviti pomoću ActionListenera, isto kao u slučaju buttona. Imajte na umu da većina korisnika nije svjesna da se nešto događa tek onda kad pritisnu return unutar TextFielda. Zato uvijek osigurajte i alternativni način ispaljivanja ActionEventa, na primjer pomoću buttona ili retka na izborniku.

Metoda getText() vraća sadržaj TextFielda. Metoda setText(String s) ga mijenja.

Metoda setEditable() omogućuje da korisniku dozvolite ili zabranite modificiranje sadržaja TextFielda.


Primjer tekstualnih polja u Javi

Sljedeći applet čita tekst iz jednog TextFielda i ispisuje ga velikim slovima u drugi TextField.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class CapitalizeApplet extends Applet {
 
  private TextField input;
  private TextField output;
  
  public void init () {
   
     // Konstruiramo tekstualna polja
     this.input = new TextField(40);
     this.output = new TextField(40);
     this.output.setEditable(false);
     Button b = new Button("Capitalize");
 
     // dodajemo komponente u razmjestaj
     this.add(input);
     this.add(b);
     this.add(output);
 
     // odredjujemo da action evente koje salju
     // button ili input TextField budu obradjeni od 
     // istog objekta tipa CapitalizerAction 
     CapitalizerAction ca = new CapitalizerAction(input, output);
     b.addActionListener(ca);
     this.input.addActionListener(ca);
 
     // ActionEvents koje salje polje output se ignoriraju.
   
   }
 
}
 
class CapitalizerAction implements ActionListener {
 
  TextField in;
  TextField out;
 
  public CapitalizerAction(TextField in, TextField out) {
    this.in = in;
    this.out = out;
  }
 
  public void actionPerformed(ActionEvent ae) {
 
    String s = in.getText();
    out.setText(s.toUpperCase());
 
  }
 
}
 
 

<APPLET CODE="CapitalizeApplet.class"

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

ARCHIVE="Capitalize.jar"

WIDTH=500 HEIGHT=100>

</APPLET>

U ovom programu korišten je drugačiji obrazac za obradu događaja. Konstruktor klase CapitalizerAction je iskorišten za prosljeđivanje referenci različitim komponentama koje metoda actionPerformed() modificira.


TextArea

Klasa java.awt.TextArea je podklasa od java.awt.TextComponent koja osigurava masku za editiranje više linija teksta. Korisna je za input i output.

Na raspolaganju su nam četiri konstruktora:

  public TextArea()
  public TextArea(String text)
  public TextArea(int rows, int columns)
  public TextArea(String text, int rows, int columns)
  public TextArea(String text, int rows, int columns, int scrollbars)

Zbog načina na koji Java raspoređuje komponente, izbjegavajte korištenje konstruktora bez argumenata. Radije počnite sa onim koji zadaje String ili broj redaka i stupaca koje će ta površina zauzeti. Na primjer,

TextArea address = new TextArea("Upišite svoju adresu", 5, 80);

Po pretpostavci, TextAreas nema scrollbar. Možete ih dodati ako odgovarajućem konstruktoru prenesete neku od ovih konstanti:

TextArea.SCROLLBARS_BOTH 
TextArea.SCROLLBARS_HORIZONTAL_ONLY 
TextArea.SCROLLBARS_NONE 
TextArea.SCROLLBARS_VERTICAL_ONLY 

Na primjer,

TextArea instructions = new TextArea("", 15, 70, TextArea.SCROLLBARS_VERTICAL_ONLY);

Za razliku od TextFielda, TextArea ne generira nikakav actionEvent kad korisnik pritisne return unutar polja. Umjesto toga, linija se prekida, a kursor prenosi u novi red.

No i nadalje, metoda getText() vraća tekst koji sadrži TextArea, a setText() ga mijenja. Metoda setEditable() dopušta vam da odredite da li će korisnik moći mijenjati sadržaj. Obje klase, TextField i TextArea, nasljeđuju sve ove metode od svoje nadklase, TextComponent.

Nadalje, tekst možete dodavati na kraj pomoću metode append(), umetati pomoću metode insert(), a zamijeniti pomoću metode replaceRange():

public synchronized void insert(String text, int position)
public synchronized void append(String text)  
public synchronized void replaceRange(String text, int start, int end)

Klasa TextComponent

I TextArea i TextField su podklase od java.awt.TextComponent. Ova klasa sadrži metode koje su zajedničke za obje klase, uključujući i nekoliko metoda koje smo već vidjeli.: getText(), setText(), i setEditable(). Klasa TextComponent ima također i metode za manipuliranje selekcijom i kursorom te za procesiranje TextEventa.

Selekcija se koristi za copy/paste ali i za druge svrhe. Prvi znak u TextComponenti je znak broj 0; drugi je znak broj 1 i tako dalje.

  public synchronized int getSelectionStart()
  public synchronized void setSelectionStart(int selectionStart)
  public synchronized int getSelectionEnd()
  public synchronized void setSelectionEnd(int selectionEnd)
  public synchronized void select(int selectionStart, int selectionEnd)
  public synchronized void selectAll()
  public synchronized String getSelectedText()

Kursor (caret) je mjesto insertiranja teksta. Tamo se pojavljuje tekst kad ga korisnik utipka. Dvije su metode koje to reguliraju:

  public void setCaretPosition(int position)
  public int getCaretPosition()

Sučelje TextListener i klasa TextEvent

Klase TextArea i TextField mogu instalirati sučelje java.awt.event.TextListener koje hvata događaje iz klase java.awt.event.TextEvent. TextComponente ispaljuju TextEvente svaki put kad se njihov tekst promijeni. To se događa uglavnom svaki put kad korisnik pritisne tipku unutar komponente.

Sučelje TextListener propisuje samo jednu metodu, textValueChanged():

public abstract void textValueChanged(TextEvent te)
 

Nekoj TextComponenti pridružujete TextListener tako da pozovete njenu metodu addTextListener(). Na primjer,

 
TextArea password = new TextArea(24)
password.addTextListener(new PasswordChecker());
 

Ipak, u najvećem broju slučajeva bit će posve dovoljno pročitati i postaviti tekst (get i set). Procesiranje znak po znak je relativno rijetko potrebno.

Napomenimo da se TextListener uklanja  pozivanjem metode removeTextListener().

public void removeTextListener(TextListener tl) 

Klasa Canvas

Klasa java.awt.Canvas definira pravokutnu površinu (podlogu, pozadinu) po kojoj možete pisati i crtati koristeći metode iz klase java.awt.Graphics. Klasa Canvas ima samo tri metode:

 
  public Canvas()
  public void addNotify()
  public void paint(Graphics g)

Podloge uglavnom ne instancirate direktno. Umjesto toga pišete podklasu koja će pregaziti paint() metodu kako biste nacrta li sliku koju trebate. Na primjer, sljedeća podklasa od Canvas crta veliku crvenu elipsu koju možete dodati vašem appletu:

import java.awt.*;
 
public class RedOval extends Canvas {
 
  public void paint(Graphics g) {
  
    Dimension d = this.getSize();
    g.setColor(Color.red);
    g.fillOval(0, 0, d.width, d.height);
      
  }
  
  public Dimension getMinimumSize() {
    return new Dimension(50, 100);  
  }
 
  public Dimension getPreferredSize() {
    return new Dimension(150, 300);  
  }
 
  public Dimension getMaximumSize() {
    return new Dimension(200, 400);  
  }
 
}

Applet koji koristi komponente nikako ne bi smio pregaziti metodu paint() jer će to zbog načina na koji Java raspoređuje  komponente izazvati nepredvidljive rezultate. Umjesto toga treba kreirati objekt tipa Canvas i sva crtanja obaviti pomoću njegove paint() metode.

Podloge se dodaju apletima na isti način kao i ostale komponente. Na primjer,

  public void init() {
    this.add(new RedOval());
  }

Podloge u pravilu ne ispaljuju nikakve događaje, no poslije ćete naučiti kako se to može promijeniti.


Klasa Choice

Klasa java.awt.Choice implementira popup izbornik sa fiksnom pozicijom (postoji također i klasa java.awt.PopupMenu kod koje pozicija nije fiksna i pojavljuje se kad korisnik klikne i drži desnu tipku miša).

Kreiranje izbornika je nešto malo kompleksnije od kreiranja komponenti koje smo do sada vidjeli. Imamo, naime, dodatni korak, dodavanje pojedinačnih opcija u izbornik. Cijeli postupak izgleda ovako:

  1. Deklarirati Choice
  2. Alocirati Choice
  3. Dodati opcije izborniku (alocirnom objektu tipa Choice)
  4. Dodati izbornik razmještaju (layout)
  5. Pridružiti ItemListener izborniku

Na primjer, prva četiri koraka mogla bi izgledati ovako

 
  public void init() {
 
    Choice ch;
    ch = new Choice();
    ch.addItem("1");
    ch.addItem("2");
    ch.addItem("3");
    ch.addItem("4");
    ch.addItem("5");
    add(ch);
 
  }

Metode klase Choice

Klasa Choice ima više metoda za dodavanje, uklanjanje i vraćanje različitih opcija sa popisa. Popis opcija se počinje brojiti od 0.

  public int getItemCount()
  public String getItem(int index)
  public synchronized void add(String item)
  public synchronized void addItem(String item)
  public synchronized void insert(String item, int position)
  public synchronized void remove(String item)
  public synchronized void remove(int position)
  public synchronized void removeAll()

Ipak, uglavnom ćete opcije ugraditi izbornik čim se applet pokrene i nećete ih kasnije mijenjati.

Sljedeće metode čitaju ili postavljaju trenutačno selektiranu opciju iz izbornika, dakle opciju koja je u tom trenutku vidljiva.

  public synchronized void removeAll()
  public synchronized String getSelectedItem()
  public synchronized Object[] getSelectedObjects()
  public int getSelectedIndex()
  public synchronized void select(int position)
  public synchronized void select(String item)

Sučelje ItemListener i klasa ItemEvent

Kad korisnik odabere novu opciju u izborniku, onda izbornik (objekt tipa Choice) ispaljuje dva događaja tipa java.awt.event.ItemEvent, jedan koji indicira da je početna opcija deselektirana i drugi, da je selektirana nova opcija. Te događaje možete procesirati tako da instalirate sučelje java.awt.event.ItemListener, a svom izborniku pridružite odgovarajući ItemListener objekt koji će hvatati spomenute događaje.

No ima i drugih načina da se to napravi. Na primjer, odabranu vrijednost iz izbornika možete provjeravati kad se dogodi neki drugi događaj, na primjer pritisak na neki button.

Pogledaj mo primjer sljedećeg appleta koji prikazuje izbornik s brojevima od d1 do 5. Korisnik biranjem broja određuje koliko puta applet šalje beep signal.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
 
public class MultiBeep extends Applet {
  
  public void init() {
 
    Choice ch;
    ch = new Choice();
    ch.addItem("1");
    ch.addItem("2");
    ch.addItem("3");
    ch.addItem("4");
    ch.addItem("5");
    this.add(ch);
    ch.addItemListener(new BeepItem());
 
  }    
 
}
 
class BeepItem implements ItemListener {
 
  public void itemStateChanged(ItemEvent ie) {
 
    if (ie.getStateChange() == ItemEvent.SELECTED) {
      String name = (String) ie.getItem();
      Toolkit tk = Toolkit.getDefaultToolkit();
      try {
        int n = Integer.parseInt(name);
        for (int i = 0; i < n; i++) tk.beep();
      }
      catch (Exception e) {
        tk.beep();
      }
    }
 
  }
 
}
 

<APPLET CODE="MultiBeep.class"

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

ARCHIVE="BeepChoice.jar"

WIDTH=200 HEIGHT=100>

</APPLET>

 

Klasa BeepItem implementira sučelje ItemListener. Ona pomoću metode ItemEvent.getStateChange() filtrira događaje prouzrokovane deselektiranjem opcija i proizvodi beep samo kad se opcija selektira. Konstante koje nam stoje na raspolaganju su:

 
ItemEvent.DESELECTED 
ItemEvent.ITEM_FIRST 
ItemEvent.ITEM_LAST 
ItemEvent.ITEM_STATE_CHANGED 
ItemEvent.SELECTED 
 

Metoda ItemEvent.getItem() se koristi da se dobije trenutno selektirana opcija. Kao i prije, ako ne možete čuti sve beepove, dodajte iza naredbi tk.beep(); u klasi BeepItem još i naredbu System.out.println("beep"); i pogledajte applet sa appletviewerom.


Klasa Checkbox

Klasa java.awt.Checkbox, se koristi za selektiranje boolean vrijednosti. Svaki Checkbox ima labelu koja bi trebala reći korisniku što pojedini Checkbox predstavlja. Na primjer Checkbox sa labelom "Olives" u appletu Ingredients za naručivanje pizze (vidi dolje) bila bi čekirana ako korisnik želi masline, a u protivnom nečekirana. Dodavanje Checkboxa appletu je jednostavno. Deklarirajte, konstruirajte i dodajte:

 
    Checkbox c;
    c = new Checkbox("Pepperoni"));
    add(c);
 

Kao i obično, ovo se može napisati i u jednoj naredbi:

 
add(new Checkbox("Pepperoni"));
 

Po pretpostavci, checkboxovi su nečekirani kad se kreiraju. Ako želite da neki od njih bude odmah čekiran, koristite sljedeći konstruktor:

add(new Checkbox("Pepperoni", null, true)); 

Vrijednost null je ovdje referenca na CheckboxGroup i znači da ovaj Checkbox ne spada u CheckboxGroup (vidi dalje).

Svaki Checkbox ima boolean vrijednost, bilo true ili false. Kad je Checkbox čekiran, ta vrijednost je true. Kad je nečekiran, ona je false. Toj vrijednosti pristupate pomoću Checkboxovih metoda getState() i setState(boolean b). Na primjer,

  private void handleCheckbox(Checkbox c) {
  
    if (c.getState()) price += 0.50f;
    else price -= 0.50f;
  
  }

Događaji iz klase Checkbox

Kad Checkbox promijeni stanje, što je u normalnim okolnostima rezultat korisnikove akcije, ispaljuje se događaj tipa java.awt.event.ItemEvent. Taj događaj uglavnom ignorirate i ispitujete stanje Checkboxa direktno kad vam treba. Ipak, ako želite odmah znati to stanje, registrirat ćete uz njega ItemListener i u odgovarajućoj klasi implementirati sučelje java.awt.event.ItemListener.

Pripadni ItemEvent je potpuno isti kao i onaj za Choice. Taj se događaj zapravo koristi za indiciranje selekcija i deselekcija u svim vrstama popisa opcija, uključujući checkboxove, radio buttone, choice, i liste.

Sljedeći program je applet koji pita "What do you want on your pizza?" Kad je dodatak čekiran, cijena se povećava za 50 centa. Kad se dodatak dečekira, cijena se smanjuje za 50 cdnta. Cijena je pokazana u TextFieldu.

import java.applet.*;
import java.awt.*;
import java.awt.event.*;
 
public class Ingredients extends Applet {
 
  TextField t;
  float price = 7.00f;
 
  public void init() {
  
    Checkbox c;
    this.add(new Label("What do you want on your pizza?", Label.CENTER));
      
    this.t = new TextField(String.valueOf(price));
    // so people can't change the price of the pizza
    t.setEditable(false); 
    Pricer p = new Pricer(price, t);
    c = new Checkbox("Pepperoni");
    this.add(c);
    c.addItemListener(p);
    c = new Checkbox("Olives");
    c.addItemListener(p);
    this.add(c);
    c = new Checkbox("Onions");
    c.addItemListener(p);
    this.add(c);
    c = new Checkbox("Sausage");
    c.addItemListener(p);
    this.add(c);
    c = new Checkbox("Peppers");
    c.addItemListener(p);
    this.add(c);
    c = new Checkbox("Extra Cheese");
    c.addItemListener(p);
    this.add(c);
    c = new Checkbox("Ham");
    c.addItemListener(p);
    this.add(c);
    c = new Checkbox("Pineapple");
    c.addItemListener(p);
    this.add(c);
    c = new Checkbox("Anchovies");
    c.addItemListener(p);
    this.add(c);
    this.add(t);
    
  }
  
}
 
class Pricer implements ItemListener {
 
  TextField out;
  double price;
 
  public Pricer(double baseprice, TextField out) {
    this.price = baseprice;
    this.out = out;
  }
  
  public void itemStateChanged(ItemEvent ie) {
  
    if (ie.getStateChange() == ItemEvent.SELECTED) this.price += 0.50f;
    else this.price -= 0.50f;
    // Change the price
    this.out.setText(String.valueOf(price));
  
  }
 
}
 

<APPLET CODE="Ingredients.class"

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

ARCHIVE="Pizza.jar"

WIDTH=200 HEIGHT=200>

</APPLET>


Klasa CheckboxGroup

Checkbox grupe su kolekcije checkboxa koje imaju specijalno svojstvo da unutar grupe ne može biti čekirano više od jednog checkboxa istovremeno. Takvi checkboxovi iz klase CheckboxGroup se često zovu radio buttons. Checkboxovi koji pripadaju istoj CheckboxGroupi ne mogu se istovremeno čekirati. Kad korisnik čekira jednog, svi ostali se automatski dečekiraju.

Konstruktor za CheckboxGroup je trivijalan. Nema argumenata i čak ne morate dodavati tu komponentu appletu jer ona nije dio korisničkog sučelja nego naprosto način uređenja checkboxova.

CheckboxGroup cbg = new CheckboxGroup();

Da biste omogućili da se jedna grupa checkboxova ponaša kao radio buttons, konstruirajte svaki pojedini na ovaj način:

public Checkbox(String label, CheckboxGroup cbg, boolean checked)

Labela label pripada određenom checkboxu, a cbg je grupa u koju stavljate taj checkbox. Ona mora u tom trenutku već postojati.

Kad god želite, možete pročitati ili odrediti koji checkbox je čekiran, koristeći se jednom od sljedeće dvije metode:

  public Checkbox getSelectedCheckbox()
  public synchronized void setSelectedCheckbox(Checkbox box)

Primjer CheckboxGroup

Sljedeći program pita korisnika kako želi platiti pizzu. Primijetite da za razliku od prethodnog primjera u kojem je mogao izabrati više dodataka na pizzu, sada može odabrati točno jedan način plaćanja.

import java.applet.*;    
import java.awt.*;
 
public class PaymentMethod extends Applet {
 
  public void init() {
    this.add(new Label("How will you pay for your pizza?"));
    CheckboxGroup cbg = new CheckboxGroup();
    this.add(new Checkbox("Visa", cbg, false));
    this.add(new Checkbox("Mastercard", cbg, false));
    this.add(new Checkbox("American Express", cbg, false));
    this.add(new Checkbox("Discover", cbg, false));
    this.add(new Checkbox("Cash", cbg, true)); // the default
  }
  
}
 

<APPLET CODE="PaymentMethod.class"

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

ARCHIVE="Pizza.jar"

WIDTH=200 HEIGHT=200>

</APPLET>

 

U ovom primjeru nije bilo nikakvih akcija. Ako želite dodati akcije, postupite jednako kao i u slučaju bilo kojeg drugog Checkboxa.


Klasa List

Liste sa scrollbarom, objekti klase java.awt.List, korisne su za spremanje duljih popisa red po red. Elementi liste su stringovi. Na primjer,


Metode klase List

Novi objekt tipa List kreirate jednim od sljedećih konstruktora:

  public List()
  public List(int numLines)
  public List(int numLines, boolean allowMultipleSelections) 

Na primjer,

List l = new List(8, true);

Pri tome je numLines broj redaka koje želite vidjeti na ekranu i on je u pravilu manji od broja elemenata same liste, dok je  allowMultipleSelections argument koji određuje može li korisnik selektirati više od jednog retka istovremeno (npr. pomoću Shift-click).

Sljedeće metode dodaju retke na kraj liste:

  public void add(String item)
  public void addItem(String item) // deprecated! Koristite prvu metodu

Sljedeće dvije metode dodaju retke na zadanu poziciju u listi:

  public synchronized void add(String item, int index)
  public synchronized void addItem(String item, int index) // deprecated!

Sljedeće metode uklanjaju retke iz liste:

  public synchronized void removeAll()
  public synchronized void remove(String item)
  public synchronized void remove(int position)
  public synchronized void delItem(int position)
 

Sljedeće  metode dopuštaju vam da pročitate određene retke iz liste:

 
  public int getItemCount()
  public String getItem(int index)
  public synchronized String[] getItems()
 

Možete također zamijeniti određeni redak:

 
  public synchronized void replaceItem(String newValue, int index)

Ove metode omogućuju vam da doznate koje je retke korisnik selektirao::

  public synchronized int getSelectedIndex()
  public synchronized int[] getSelectedIndexes()
  public synchronized String getSelectedItem()
  public synchronized String[] getSelectedItems()
  public Object[] getSelectedObjects()

Množinski oblik ovih metoda koristit ćete ako lista dozvoljava višestruku selekciju. Da li je ona dozvoljena, ustanovit ćete metodom isMultipleMode(), a to možete promijeniti pomoću setMultipleMode().

  public boolean isMultipleMode()
  public synchronized void setMultipleMode(boolean b)

Sljedeće metode omogućuju vam manipuliranje selektiranjem:

  public synchronized void select(int index)
  public synchronized void deselect(int index)
  public boolean isIndexSelected(int index)

Sljedeće dvije metode određuju da li je redak na određenom indeksu vidljiv unutar kućice:

  public int getVisibleIndex()
  public synchronized void makeVisible(int index)

 

Događaji klase List

Lists can fire two separate types of events. When a list item is selected or deselected, the List fires an ItemEvent. However, when the user double clicks on a list item, the List fires an ActionEvent. Therefore, you can register both an ItemListener to process selections and/or an ActionListener to process double clicks.

 
public void addItemListener(ItemListener l)
public void removeItemListener(ItemListener l)
public void addActionListener(ActionListener l)
public void removeActionListener(ActionListener l)
 

The action command in the ActionEvent is the list item which was double clicked.


Klasa Scrollbar

Klase List, TextArea, i ScrollPanes imaju gotove scrollbare. No ako želite scrollati neki drugi objekt, treba vam klasa java.awt.Scrollbar. Scrollbari imaju puno primjena. Elementarna je pomicanje vidljivog područja. Također se mogu koristiti za postavljanje vrijednosti između dva zadana broja. Ili mogu prolaziti kroz više ekrana, kao u operacijama na bazama podataka koje traže sukcesivne slogove.

Imamo tri konstruktora:

public Scrollbar()
public Scrollbar(int orientation)
public Scrollbar(int orientation, int value, int visible, int min, int max)
 

Argument orientation je jedna od mnemoničkih konstanti, Scrollbar.HORIZONTAL ili Scrollbar.VERTICAL. Prema očekivanju, one određuju da li je scrollbar razmješten s lijeva na desno ili odozgo prema dolje.

Sve vrijeme Scrollbar ima jednu an int vrijednost. To je početna vrijednost koja mora biti između minimalne i maksimalne koje se zadaju sa zadnja dva argumenta. Kad se Scrollbar kreira, njegova početna vrijednost će biti value. Default je 0.

Argument visible predstavlja veličinu vidljivog dijela skrolabilne površine u pikselima. To se koristi kod pomicanja po stranici.

Događaj koji Scrollbar ispaljuje je tipa java.awt.event.AdjustmentEvent. Klasa koja će ga uhvatiti mora implementirati sučelje java.awt.event.AdjustmentListener. Ona mora implementirati metodu adjustmentValueChanged() sa sljedećom signaturom:

public void adjustmentValueChanged(AdjustmentEvent e)

Sljedeći program je applet koji mijenja broj u TextFieldu između 1 i 100 u ovisnosti o poziciji oznake na scrollbaru. U praksi bi taj broj, naravno, morao nešto predstavljati.

import java.applet.*;    
import java.awt.*;
import java.awt.event.*;
 
public class Scrollie extends Applet implements AdjustmentListener {
 
  TextField t;
  Scrollbar sb;
 
  public void init() {
    int initialValue = 1;
    sb = new  Scrollbar(Scrollbar.HORIZONTAL, initialValue, 1, 1, 100);
    sb.addAdjustmentListener(this);
    this.add(sb);
    this.t = new TextField(4);
    this.t.setText(String.valueOf(initialValue));    
    this.add(t);
  }
  
  public void adjustmentValueChanged(AdjustmentEvent e) {
     
    int val = sb.getValue();
    this.t.setText(String.valueOf(val));
    
  }
  
}
 

<APPLET CODE="Scrollie.class"

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

WIDTH=200 HEIGHT=100>

</APPLET>