Uvod u programiranje

Maja Čić


Događaji i interaktivnost

Događaji su, poput svega u Javi, predstavljeni objektima. Postoji nekoliko različitih vrsta događaja, a svaka vrsta zasebno predstavljena je klasom. Sve klase događaja korištene u AWT-u su podklase apstraktne klase java.awt.AWTEvent. Klase događaja koje opisuju točno određene vrste događaja, poput MouseEvent i ActionEvent, nalaze se u paketu java.awt.event.

Da bi događaj imao utjecaj, potrebno je da program otkrije događaj i odgovori na njega. Za svaku klasu događaja postoji interface koji određuje jednu ili više metoda za odgovor na događaje te klase. Na primjer uz klasu ActionEvent vezan je interface koji se zove ActionListener. To sučelje definira metodu, "public void actionPerfromed(ActionEvent evt)". Objekt koji želi odgovoriti na događaje mora primjeniti ovaj interface. Na primjer, ako aplet MyApplet treba odgovoriti na događaje, definicija klase apleta mora izgledati ovako:

       public class MyApplet extends Applet implements ActionListener {
       
          . . .   // druge varijable, metode, itd.
          
          public void actionPerformed(ActionEvent evt) {
          
             . . . // odgovor na događaj (action event) evt
             
          }
          
          . . . // druge varijable, metode, itd.
          
       }

Primjenom ActionListener sučelja, objekt postaje sposoban "slušati" događaje. Ali prije nego može stvarno "čuti" događaje, mora biti prijavljen kao slušač događaja (action listener). Događaje stvaraju komponente. Tako, na primjer, kad korisnik pritisne tipku, generira se jedan događaj. Svaka komponenta koja može stvarati događaje ima definiranu metodu addActionListener, koja služi za prijavljivanje slušača događaja kod komponente. Kad komponenta stvori događaj, obavještava sve prijavljene slušače događaja pozivanjem njihovih actionPerformed() metoda.

Na primjer, ako MyApplet kreira tipku commandButton i želi primiti obavijest kad korisnik pritisne tu tipku, aplet mora pozvati metodu commandButton.addActionListener(this). Riječ this odnosi se na sam aplet , a znači da će obavijest biti poslana apletu pozivanjem actionPerfomed() metode apleta. Očito, mjesto na kojem će aplet kreirati commandButton i postaviti sebe kao slušača je init() metoda koja bi onda izgledala ovako:

       
       public void init() {   // inicijalizacijska metoda za aplet definiran klasom MyApplet
          . . . // neke naredbe
          commandButton = new Button("Do It!");
          commandButton.addActionListener(this);
          . . . // dodaj commandButton u aplet ili u neki container
          . . . // još naredbi
       }

Naravno, svaki objekt može imati ulogu slušača događaja pod uvjetom da primjenjuje ActionListener sučelje, ne mora to biti aplet s tipkom, pa niti ni GUI komponenta.

Prilikom poziva actionPerformed() metode, prosljeđuje joj se parametar tipa ActionEvent koji sadrži podatke o određenom događaju koji se dogodio. Metode za pristup ovim podacima su određene u ActionEvent klasi. Svaki tip događaja je predstavljen različitom klasom jer svaki zasebni tip događaja šalje slušačima različite podatke.


Praćenje događaja za miša

Postoje dvije klase događaja vezane uz miš: MouseEvent i MouseMotionEvent. Također postoje dva sučelja za slušanje: MouseListener i MouseMotionListener. Sučelje MouseLlistener deklarira metode:

       public void mousePressed(MouseEvent evt);
       public void mouseReleased(MouseEvent evt);
       public void mouseClicked(MouseEvent evt);
       public void mouseEntered(MouseEvent evt);
       public void mouseExited(MouseEvent evt);
   
a MouseMotionListener deklarira
       public void mouseMoved(MouseEvent evt);
       public void mouseDragged(MouseEvent evt);

Sve komponente mogu generirati događaje miša. Objekt koji želi odgovoriti na ove događaje mora implementirati jedno ili oba ova sučelja. Također se mora prijaviti kod komponente pozivanjem metode addMouseListener() i/ili addMouseMotionListener(). Objekt koji primjenjuje MouseLIstener mora dati definicije za svih pet metoda u tom sučelju, čak i ako se sastoje od praznih zagrada. Slično tome, objekt koji primjenjuje MouseMotionListener sučelje mora definirati i mouseMoved() i mouseDragged() metode.

Komponenta poziva mousePressed() metodu kad god je jedna od tipki na mišu pritisnuta dok je pokazivač iznad komponente. Nakon toga će pozvati mouseReleased() metodu nakon što se tipku pusti, čak i ako se pokazivač pomakao izvan komponente. Metoda mouseClicked() poziva se ako je tipka pritisnuta i puštena na istom mjestu. Poziva se kao dodatak mousePressed() i mouseReleased() metodama. Ako bi željeli jednostavno odgovarati ne pritiske tipki na mišu, najjednostavnije je raditi s mousePressed() metodom, a definicije mouseReleased() i moseClicked() ostaviti prazne.

Metoda mouseDragged() poziva se kad korisnik pomiče miša držeći pritisnutu jednu od tipki na mišu. Broj poziva mouseDragged() metode između poziva mousePressed() i mouseReleased() nije ograničen, a uvijek se poziva mouseDragged() metoda klase elementa u kojem je tipka prvi put pritisnuta, čak i kad je pokazivač izašao iz te komponente.

Metode mouseEntered(), mouseExited() i mouseMoved() rijeđe se koriste, a odnose se na kretanje miša dok ni jedna tipka nije pritisnuta. Njihova značenja su očita: mouseEntered() i mouseExited() se mogu, na primjer, koristiti za promjenu izgleda komponente dok je pokazivač na njoj, a mouseMoved() se može koristiti za pomicanje nekog pokazivača po ekranu. Promotrimo to na primjeru platna koje mijenja boju kad korisnik pritisne tipku na njemu:

       class ColorChangeCanvas extends Canvas implements MouseListener {
       
          int currentColor = 0;  // 0 za crvenu, 1 za plavu, 2 za zelenu          
          ColorChangeCanvas() { // konstruktor
             setBackground(Color.red);
             addMouseListener(this);  // Canvas će "slušati" vlastite događaje miša.

          }
          
          public void mousePressed(MouseEvent evt) {
                // Kada je korisnik kliknuo na platno;
                // mijenja boju svoje pozadine i ponovno iscrtava aplet.
             currentColor++;
             if (currentColor > 2)
                currentColor = 0;
             switch (currentColor) {
                case 0: setBackground(Color.red); break;
                case 1: setBackground(Color.blue); break;
                case 2: setBackground(Color.green); break;
             }
             repaint();
          }
          
          public void mouseReleased(MouseEvent evt) { }   // Definicije koje
          public void mouseClicked(MouseEvent evt) { }    // zahtijeva MouseListener
          public void mouseEntered(MouseEvent evt) { }    // sučelje.
          public void mouseExited(MouseEvent evt) { }
        
       } // end class ColorChangeCanvas   

U ovom slučaju ista klasa koja generira događaje miša ujedno i sluša te događaje, što je česta pojava za događaje miša i tipkovnice.

Često je potrebno odrediti položaj pokazivača na ekranu u trenutku kad je tipka na mišu pritisnuta. Ovaj podatak se može dobiti kroz parametar evt tipa MouseEvent. Za dobijanje položaja pokazivača potrebno je pozvati evt.getX() i evt.getY() metode koje vraćaju cjelobrojne vrijednosti x i y koordinate koordinatnog sustava komponente pri čemu je gornji lijevi kut (0,0).

Metoda evt.isMetaDown() vraća logičku vrijednost true ako je pritisnuta desna tipka na mišu, a evt.isAltDown() vraća true ako je pritisnuta srednja tipka na mišu.

Sljedeći primjer apleta odgovara na bilo koji od sedam mogućih događaja miša prikazujući koordinate pokazivača, vrstu događaja i popis svih pritisnutih modifikatorskih tipki (Shift, Control, Meta, Alt). Izvorni kod apleta je u SimpleTrackMouse.java .

Jedna od radnji koje je moguće obavljati mišem je povlačenje. Povlačenje znači pomicanje miša uz istovremeno držanje pritisnute tipke na mišu. Da bi komponenta odgovorila na povlačenje, potrebno je napisati tri metode: mousePressed(), mouseDragged() i mouseReleased(). Odgovor na jednu radnju povlačenja je raspoređen preko tri metode. Osim toga, mouseDragged() metoda može biti pozvana više puta dok se miš pomiče. Potrebno je postaviti nekoliko varijabli instance koje prate šta se događa između poziva metode. Razmotrimo primjer programa koji omogućava korisniku crtanje krivulja mišem, znači prilikom svakog pomaka miša crta liniju između prethodne i sadašnje lokacije pokazivača:

        int prev_x;  // prethodna x koordinata miša
        int prev_y;  // prethodna y koordinata miša
        
        public void mousePressed(MouseEvent evt) {
           prev_x = evt.getX();  // zabilježi položaj miša
           prev_y = evt.getY();
        }
        
        public void mouseDragged(MouseEvent evt) {
           int new_x = evt.getX();
           int new_y = evt.getY();
           ... // nacrtaj crtu između (prev_x,prev_y) i (new_x,new_y)
           prev_x = new_x;
           prev_y = new_y;
        }
        
        public void mouseReleased(MouseEvent evt) {
           int new_x = evt.getX();
           int new_y = evt.getY();
           ... // nacrtaj crtu između (prev_x,prev_y) i (new_x,new_y)
        }

Sljedeći aplet je jednostavni primjer programa koji koristi ovu tehniku. Aplet koristi sliku koja nije prikazana na ekranu da bi spremio kopiju skice, da bi je mogao ponovo nacrtati ako bude potrebno. Kad god treba isctati sliku, ona se iscrtava na samom apletu i na pričuvnoj kopiji u neprikazanoj slici. Dodatna mogućnost ovog apleta je brisanje skice pritiskom na desnu tipku miša. Izvorni kod ovog jednostvnog programa za skiciranje nalazi se u datoteci TrivialSketch.java .




[ prethodna stranica | Početak | sljedeća stranica ]