11. Meer over methoden

Als je een programma compileert waarin de methode action voorkomt, heb je misschien gemerkt dat Java een waarschuwing geeft. De methode action (en enkele andere methoden) zijn namelijk wat verouderd en zijn inmiddels vervangen door methoden (de zogenaamde Listener methoden), die wat efficiënter werken.

Deze nieuwere methoden zijn onderdelen van zogenaamde interfaces. Maar wat is een interface?

Elke applet die we tot dusver maakten begon met:

public class ZusOfZo extends Applet {

De toevoeging extends Applet houdt in dat dit programma alle functionaliteit erft van de klasse Applet. Dat wil zeggen dat applets bijvoorbeeld 'weten' hoe ze moeten omgaan met methodes als init en paint. Helaas kunnen klassen via overerving slechts van één andere klasse erven.

Net zoals bij overerving (dus via extends), biedt een interface de mogelijkheid om een programma extra functionaliteit mee te geven. De opname van zo'n interface heeft één belangrijk nadeel en één belangrijk voordeel ten opzichte van erving:

  • Een voordeel is dat een klasse van meer dan één interface kan erven.
  • Een nadeel is dat alle methoden van de interface moeten worden opgenomen.

   

De interface ActionListener

In de applets die we tot dusver maakten, kon een ingetypte tekst alleen naar een string-variabele worden gekopieerd als op een knop werd geklikt. Maar het is vaak prettiger als je na invoer gewoon op de Enter-toets kan drukken.

We kunnen dit bereiken met de interface ActionListener. Hiervoor moeten we vier regels aan ons programma toevoegen:

  1. aan het begin een extra package opnemen met: import java.awt.event.*;
  2. in de kopregel vermelden dat het om een interface gaat met: ... implements ActionListener
  3. de interface koppelen aan het tekstvak in de methode init met vak.addActionListener(this);
  4. deze interface heeft maar één methode, namelijk: public void actionPerformed (ActionEvent ae)
Een eenvoudige demonstratie van de werking van deze interface zie je in het volgende programma, waarin we ook een methode zien (van het type String) die een woord "omkeert".

// Eenvoudige demonstratie van
// de interface ActionListener
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class ActionListenerDemo extends Applet
                        implements ActionListener {
   TextField vak = new TextField(20);
   String woord1 = "Type 'n woord en druk <Enter>";
   String woord2 = "";

   public void init () {
      add (vak);
      vak.addActionListener (this);
   }

   public void paint (Graphics g) {
      g.drawString (woord1, 20, 120);
      g.drawString (woord2, 20, 160);
      vak.requestFocus();
   }

   public void actionPerformed (ActionEvent ae) {
      String ingetypt = vak.getText();
      woord1 = "Je tikte in: " + ingetypt;
      woord2 = "Omgekeerd: " + keerom (ingetypt);
     vak.setText("");
     repaint();
   }

   String keerom (String s) {
      String temp = "";
      for (int i=s.length()-1; i>=0; i--)
         temp += s.charAt (i);
     return temp;
   }
}

   

MouseListener

Een tweede serie Listener-methoden vinden we in de interface MouseListener. Ook deze interface voegen toe we in vier stappen:

  1. opname van de package java.awt.event met: import java.awt.event.*;
  2. toevoegen van de interface aan het programma met: . . .  implements MouseListener
  3. de interface (in init) koppelen aan de applet: addMouseListener (this);
  4. deze interface heeft de volgende vijf methoden, die we allemaal moeten opnemen, of we ze gebruiken of niet:
    public void mouseClicked (MouseEvent evt) { }
    public void mousePressed (MouseEvent evt) { }
    public void mouseReleased (MouseEvent evt) { }
    public void mouseEntered (MouseEvent evt) { }
    public void mouseExited (MouseEvent evt) { }

De methoden die in dit hoofdstuk geïntroduceerd zijn gaan we gebruiken in een programma dat ons driehoeken laat tekenen door met de muis te klikken.

Om het venster weer leeg te maken, gaan we een knop aanbrengen die een complete repaint verricht.

Maar tot dan moeten de getekende driehoeken wel op het beeldscherm blijven staan. Dus dan kunnen we geen repaint gebruiken. Anders zouden we telkens maar één lijntje kunnen tekenen. We gaan dit oplossen door het mechanisme dat de applet tekent te "overriden". Overriden betekent dat we geen gebruik maken van een standaard mechanisme, maar dit vervangen door een zelfgeschreven methode.

Het tekenwerk in een applet wordt standaard geregeld door een methode die update heet. Deze methode vult eerst de achtergrond van het appletvenster op, waardoor het venster feitelijk wordt gewist. Hierna wordt paint aangeroepen, die het tekenwerk verricht.

We kunnen deze echter overriden door een eigen versie van update te schrijven, die paint alleen laat tekenen, maar die niets uitwist. Dat kan heel simpel, bijvoorbeeld zo:

public void update (Graphics g) {
   paint (g);
}

Een belangrijk aspect van computerprogramma's waar mensen mee omgaan is feedback. De mens ziet graag dat het programma op hem reageert. Per slot van rekening verwachten wij ook een reactie als we met mensen communiceren.

Om deze feedback te leveren, gaan we op plaatsen waar in onze applet geklikt wordt, een stip tekenen. Hiervoor kan de methode mouseClicked ons de coördinaten leveren, aldus:

public void mouseClicked (MouseEvent evt) {
   x [beurt] = evt.getX ( );
   y [beurt] = evt.getY ( );
   beurt ++;
   update (getGraphics());
}

Je ziet dat we de coördinaten opslaan in twee arrays (x[ ] en y[ ]), die zo zijn gedefinieerd:

int x[ ] = new int [3], y[ ] = new int [3];
int beurt = 0;

Als we de variabele beurt de waarden 0, 1 en 2 laten doorlopen, zal de methode mouseClicked keurig drie setjes coördinaten opvangen. Als op de reset-knop is geklikt, vegen we alles uit door een rechthoek met de kleur wit te vullen.

Anders tekenen we een stip op het aangeklikte punt. Bij het derde punt laten we telkens een nieuwe driehoek tekenen door onze methode driehoek, aldus:

if (reset) {
   g.setColor (Color.white);
   g.fillRect (0,0,getSize().width,getSize().height);
   reset = false;
   g.setColor (Color.black);
}
else {
   if (beurt>0)
      g.drawOval (x[beurt-1], y[beurt-1],1,1);
   if (beurt==3) {
      driehoek(g,x[0],y[0],x[1],y[1],x[2],y[2]);
      beurt = 0;
   }
}

De rest van het programma spreekt hopelijk voor zichzelf:

// Driehoeken tekenen 
import java.applet.*;
import java.awt.*;
import java.awt.event.*;
public class TekenDriehoek extends Applet
       implements ActionListener, MouseListener {
   int x[]=new int[3], y[]=new int[3], beurt = 0;
   Button knop = new Button ("nieuw");
   boolean reset;

   public void init () {
      addMouseListener (this);
      add (knop);
      knop.addActionListener (this);
   }

   public void paint (Graphics g) {
      if (reset) {
         g.setColor (Color.white);
         g.fillRect (0,0,getSize().width,getSize().height);
         reset = false;
         g.setColor (Color.black);
      }
      else {
         if (beurt>0)
            g.drawOval (x[beurt-1], y[beurt-1],1,1);
         if (beurt==3) {
            driehoek(g,x[0],y[0],x[1],y[1],x[2],y[2]);
            beurt = 0;
         }
      }
   }

   public void driehoek (Graphics g, int x1, int y1,
      int x2, int y2, int x3, int y3) {
      g.drawLine (x1, y1, x2, y2);
      g.drawLine (x2, y2, x3, y3);
      g.drawLine (x3, y3, x1, y1);
   }

   public void mouseClicked (MouseEvent evt) {
      x[beurt] = evt.getX();
      y[beurt] = evt.getY();
      beurt++;
      update(getGraphics());
   }

   public void mousePressed (MouseEvent evt) {}
   public void mouseReleased (MouseEvent evt) {}
   public void mouseEntered (MouseEvent evt) {}
   public void mouseExited (MouseEvent evt) {}
   public void update(Graphics g) {
      paint (g);
   }

   public void actionPerformed (ActionEvent ae) {
      beurt = 0;
      reset = true;
      update(getGraphics());
   }
}

   

Een werkende applet zie je hier:

   

Opdracht 11.1

Schrijf een applet waarin een zin kan worden ingetypt in een tekstvak. Na indrukken van de enter-toets wordt het vak leeggemaakt en wordt de zin opnieuw getoond en wordt er meegedeeld hoeveel klinkers (a, e, i, o, u, ook als hoofdletters) de zin bevat. Dit tellen moet gedaan worden in een aparte methode die als return-waarde het aantal klinkers afgeeft.

   

Opdracht 11.2

Schrijf een applet waarin bij elke klik een lijnstuk wordt bijgetekend vanaf het laatst getekende tot het nieuw aangeklikte punt. Het tekenen begint in de linkerbovenhoek bij een vlakje met daarin het woord "reset". Bij klikken op dat vlakje start het programma opnieuw.

   

(c) 2003-2008, Thomas J.H.Luif