Lyssnare

På denna sida beskrivs kortfattat hur man i Java använder knappar och andra grafiska komponenter. Det är inte nödvändigt att förstå allt detta för att göra labb 3. Den som vill läsa mer än denna kortfattade beskrivning kan göra det i kapitel 6 i Ecks bok.

En knapp i ett program med grafiskt användargränssnitt (GUI) bör, om GUI:t är väl utformat, ha en text (eller en ikon) som gör det tydligt för användaren vad som händer om man klickar på knappen. I det program ni fått i labb 3 finns tre knappar, med texterna Step, Run och Stop. Java-koden för knapparna finns i LifeView.java. Man ser där att en knapp är en instans av klassen JButton. Ni har också sett att i det givna programmet har klickande på knapparna ingen effekt.

Step-knappen

Step-knappen kommer att fungera om ni lägger till
  ActionListener stepListener = new StepListener();
  stepButton.addActionListener(stepListener);

till konstrueraren. För att förstå hur detta fungerar behöver man veta följande:

Det som är viktigt att förstå är hur vi som programmerare skriver kod (actionPerformed, paintComponent), som kommer att anropas när användaren gör saker (i detta fall trycker på en knapp).

I det givna programmet gör det grafiska gränssnittet vad det kan för att programmet ska fungera; det anropar modellobjektet för att beräkna en ny generation. Men den givna modellklassen LifeModel räknar inte alls ut någon ny generation enligt reglerna för Game of Life. Detta är vad ni ska fixa.

De andra två knapparna

En annan fördefinierad Java-klass är Timer. Ett objekt av denna klass skapas också i LifeView:

timer = new Timer(100,stepListener);

Detta skapar ett objekt timer med följande beteende: var 100:e millisekund anropar den stepListener.actionPerformed, vilket leder till att en ny generation beräknas och ritas ut. Men en Timer börjar inte göra det förrän den startats; därefter håller den på tills den stoppas. Titta på lyssnarklasserna för de två andra knapparna så ser ni att de gör precis dessa saker.

Mushändelser

När man klickar med musen i världen är det meningen att denna cell ska byta tillstånd. Detta beskrivs i LifeWorld.java:

public void mouseClicked(MouseEvent e) {
    int i = e.getX()/xside;
    int j = e.getY()/yside;
    boolean b = model.getCell(i,j);
    model.setCell(i,j,!b);
    repaint();
}

Förutom metoden mouseClicked definieras fyra ytterligare metoder med namn som börjar på mouse, men ingen av dessa gör något. Dessa fem metodsignaturer bildar interfacet MouseListener. Genom att registrera ett objekt av en klass som imlementerar MouseListener som lyssnare hos panelen (med addMouseListener) kommer vi att få effekten att detta objekts olika metoder anropas vid olika händelser: mouseClicked när man klickar med musen; mousePressed när man trycker ner musknappen; mouseReleased när man släpper knappen; mouseEntered när muspekaren kommer in över panelen; och mouseReleased när muspekaren lämnar panelen. Dessutom kommer parametern i metodanropet att ha information om var (i vilka koordinater) händelsen inträffar.

Vi ser att mouseClicked tar reda på koordinaterna för att få reda på vilken cell som ska uppdateras. Sedan tillfrågas modellen om cellens nuvarande tillstånd innan den beordras uppdatera cellen med motsatt värde.

I det här fallet har vi valt att inte definiera en särskild klass som implementerar MouseListener; vi låter helt enkelt klassen LifeView själv göra också detta och använder this som parameter till addMouseListener. För att få hävda att klassen implementerar MouseListener måste vi också definiera alla fem metoderna i interfacet, fast vi egentligen bara vill göra något i fallet mouseClicked.