# Problem mit Eventhandling (Anfängerfrage)



## Simighourt (3. Jun 2006)

Hallo, ich bin immer noch an meinem JavaPhone Projekt. Jetzt grade beim Eventhandling. Wenn die Nummerntasten gedrückt werden sollen wie bei einem Telefon die Ziffern im Display erscheinen. Als Anleitung dafür habe ich ein Blatt aus dem Info-Unterricht benutzt. Scheint aber nicht wirklich genau so zu funktionieren wie darauf beschrieben. Hier der Code:

```
import java.awt.*;

class JavaPhoneGui extends Frame {
  Button key1 = new Button("1");
  Button key2 = new Button("2");
  Button key3 = new Button("3");
  Button key4 = new Button("4");
  Button key5 = new Button("5");
  Button key6 = new Button("6");
  Button key7 = new Button("7");
  Button key8 = new Button("8");
  Button key9 = new Button("9");
  Button key0 = new Button("0");
  Button key_raute = new Button("#");
  Button key_stern = new Button("*");
  Button hookoff = new Button("Hook off");

  TextField display = new TextField();
  Label state = new Label("ready");
  Panel keyPanel = new Panel();
  Panel keyDisplayPanel = new Panel();
  Panel statePanel = new Panel();

  JavaPhoneGui() {
    setLayout(new BorderLayout(2,2));
    keyPanel.setLayout(new GridLayout(4,3,2,2));
    keyDisplayPanel.setLayout(new     BorderLayout(2,2));
    statePanel.setLayout(new BorderLayout(2,2));

    keyPanel.add(key1);
    keyPanel.add(key2);
    keyPanel.add(key3);
    keyPanel.add(key4);
    keyPanel.add(key5);
    keyPanel.add(key6);
    keyPanel.add(key7);
    keyPanel.add(key8);
    keyPanel.add(key9);
    keyPanel.add(key_raute);
    keyPanel.add(key0);
    keyPanel.add(key_stern);

    keyDisplayPanel.add(display, BorderLayout.NORTH);
    keyDisplayPanel.add(keyPanel, BorderLayout.CENTER);
    statePanel.add(hookoff,BorderLayout.CENTER);
    statePanel.add(state, BorderLayout.NORTH);

    add(keyDisplayPanel, BorderLayout.CENTER);
    add(statePanel, BorderLayout.WEST);
    

    setTitle("JavaPhone");
    setSize(300,300);
    setLocation(300,300);
    setResizable(false);
    setVisible(true);
    
    key1.addActionListener(new KeyListener());
    key2.addActionListener(new KeyListener());
    key3.addActionListener(new KeyListener());
    key4.addActionListener(new KeyListener());
    key5.addActionListener(new KeyListener());
    key6.addActionListener(new KeyListener());
    key7.addActionListener(new KeyListener());
    key8.addActionListener(new KeyListener());
    key9.addActionListener(new KeyListener());
    key0.addActionListener(new KeyListener());
    key_raute.addActionListener(new KeyListener());
    key_stern.addActionListener(new KeyListener());
    hookoff.addActionListener(new KeyListener());
  }
}

class KeyListener implements ActionListener {
  actionPerformed(ActionEvent e) {
    String ziffer = e.getActionCommand();
    display.setText(display.getText()+ziffer);
  }
}
```

Beim Compilieren bekomme ich folgende Meldung:



> simon@simon:/daten/schule/java/JavaPhone$ javac JavaPhoneGui.java
> JavaPhoneGui.java:75: invalid method declaration; return type required
> actionPerformed(ActionEvent e) {
> ^
> 1 error


Erscheint eigentlich recht logisch die Meldung. Welchen Ausgabetyp hat den eine solche actionPerformed-Methode? Oder habe ich etwas anderes falsch gemacht? Danke für schnelles posten^^
Simon


----------



## L-ectron-X (3. Jun 2006)

Die Methode aus ActionListener heißt
_public void actionPerformed(ActionEvent e)_
und muss auch genau so überschrieben werden.

Und: Der Klassenname KeyListener ist sehr ungünstig gewählt, weil es im event-Package bereits ein solches Interface gibt. Das könnte mal Probleme geben, wenn du wirklich einen KeyListener in dieser Klasse brauchst.


----------



## Simighourt (3. Jun 2006)

Ok, ich habe die Zeile geändert und meine neue Klasse einfach Listener genannt. Jetzt bekomme ich folgende Meldung:



> simon@simon:/daten/schule/java/JavaPhone$ javac JavaPhoneGui.java
> JavaPhoneGui.java:74: cannot resolve symbol
> symbol  : class ActionListener
> location: class Listener
> ...


Was genau bedeutet das?


----------



## Illuvatar (3. Jun 2006)

Du solltest vor allem mal java.awt.event importieren.


----------



## L-ectron-X (3. Jun 2006)

Ich habe mal noch drei Fehler korrigiert.
1. Du musst noch das Package java.awt.event importieren.
2. Wenn du das so machst, musst deine Listener-Klasse als innere Klasse angelegt sein, da diese sonst nicht auf die Instanzvariablen Zugriff hat.
3. Instanzvariablen private deklarieren.
4. Code zum Schließen des Fensters eingebaut.
5. main()-Methode zum Starten/Testen eingefügt.

Der Code sieht danach nun so aus:

```
import java.awt.*;
import java.awt.event.*;

class JavaPhoneGui extends Frame {
  private Button key1 = new Button("1");
  private Button key2 = new Button("2");
  private Button key3 = new Button("3");
  private Button key4 = new Button("4");
  private Button key5 = new Button("5");
  private Button key6 = new Button("6");
  private Button key7 = new Button("7");
  private Button key8 = new Button("8");
  private Button key9 = new Button("9");
  private Button key0 = new Button("0");
  private Button key_raute = new Button("#");
  private Button key_stern = new Button("*");
  private Button hookoff = new Button("Hook off");

  private TextField display = new TextField();
  private Label state = new Label("ready");
  private Panel keyPanel = new Panel();
  private Panel keyDisplayPanel = new Panel();
  private Panel statePanel = new Panel();

  JavaPhoneGui() {
    setLayout(new BorderLayout(2,2));
    keyPanel.setLayout(new GridLayout(4,3,2,2));
    keyDisplayPanel.setLayout(new BorderLayout(2,2));
    statePanel.setLayout(new BorderLayout(2,2));
    
    addWindowListener(new WindowAdapter() {
       public void windowClosing(WindowEvent e) {
          System.exit(0);
       }
    });

    keyPanel.add(key1);
    keyPanel.add(key2);
    keyPanel.add(key3);
    keyPanel.add(key4);
    keyPanel.add(key5);
    keyPanel.add(key6);
    keyPanel.add(key7);
    keyPanel.add(key8);
    keyPanel.add(key9);
    keyPanel.add(key_raute);
    keyPanel.add(key0);
    keyPanel.add(key_stern);

    keyDisplayPanel.add(display, BorderLayout.NORTH);
    keyDisplayPanel.add(keyPanel, BorderLayout.CENTER);
    statePanel.add(hookoff,BorderLayout.CENTER);
    statePanel.add(state, BorderLayout.NORTH);

    add(keyDisplayPanel, BorderLayout.CENTER);
    add(statePanel, BorderLayout.WEST);

    setTitle("JavaPhone");
    setSize(300,300);
    setLocation(300,300);
    setResizable(false);
    setVisible(true);

    key1.addActionListener(new Listener());
    key2.addActionListener(new Listener());
    key3.addActionListener(new Listener());
    key4.addActionListener(new Listener());
    key5.addActionListener(new Listener());
    key6.addActionListener(new Listener());
    key7.addActionListener(new Listener());
    key8.addActionListener(new Listener());
    key9.addActionListener(new Listener());
    key0.addActionListener(new Listener());
    key_raute.addActionListener(new Listener());
    key_stern.addActionListener(new Listener());
    hookoff.addActionListener(new Listener());
  }

   class Listener implements ActionListener {
     public void actionPerformed(ActionEvent e) {
       String ziffer = e.getActionCommand();
       display.setText(display.getText()+ziffer);
     }
   }
   
   public static void main(String[] args) {
      new JavaPhoneGui();
   }
}
```


----------



## Leroy42 (3. Jun 2006)

Wenn du (Lectron) dir schon so viel Mühe gegeben hast,
den Source zu korrigieren, dann verstehe ich nicht,
wieso du SemiJoghurt nicht darauf hingewiesen hast, daß

```
key1.addActionListener(new Listener()); 
    key2.addActionListener(new Listener()); 
    key3.addActionListener(new Listener());
    ...
```

unnötig ist. Da der Listener sowieso schon nachschaut,
durch welchen Button er aktiviert wurde, brauch doch
nicht jeder key einen eigenen Listener. Für _Linksdrehend_:


```
ActionListener al = new Listener();
    key1.addActionListener(al); 
    key2.addActionListener(al); 
    key3.addActionListener(al);
    ...
```


----------



## L-ectron-X (3. Jun 2006)

Hast natürlich recht! Mein Fehler. Mach ich nie, nie wieder. :wink:
Schlimmer finde ich, dass du, Leroy23, meinen Nick nicht richtig schreiben kannst... :wink:  :lol:


----------



## Leroy42 (3. Jun 2006)

Tja, du hast dir das Wochende redlich verdient.   

[schild=6 fontcolor=000000 shadowcolor=C0C0C0 shieldshadow=1]Zweideutigkeiten dürfen ohne Rücksprache entsorgt werden.[/schild]


----------



## Leroy42 (3. Jun 2006)

L-ectron-X hat gesagt.:
			
		

> Schlimmer finde ich, dass du, Leroy23, meinen Nick nicht richtig schreiben kannst... :wink:  :lol:



Das ist meine natürlich Faulheit(*) und bedeutet keine Herabwürdigung.


Aber ich bin ja nicht so: Wenn ich irgendwann mal mein Multi-Copy-Paste-Utility
in Java verwirklicht habe, bekommt dein Name einen Top-10 Eintrag; damit können
wir dann beide leben  :toll: 

[schild=11 fontcolor=000000 shadowcolor=C0C0C0 shieldshadow=1](*)Wer keinen Sinn für Faulheit hat, kann kein guter Programmierer werden![/schild]


----------



## Simighourt (3. Jun 2006)

Ja, besten Dank, jetzt funktioniert es!


----------



## Simighourt (3. Jun 2006)

Moment, eine Frage hätte ich dann doch noch: Was ist das:

```
addWindowListener(new WindowAdapter() {
       public void windowClosing(WindowEvent e) {
          System.exit(0);
       }
    });
```
Habe diese "Klammer-Konstruktion" noch nie gesehen  :shock:


----------



## L-ectron-X (3. Jun 2006)

Das ist eine Anweisung, in welcher ein Objekt einer so genannten anonymen Klasse (sie hat keine Referenz mit einem Namen) erzeugt wird. Innerhalb dieser Klasse, welche von WindowAdapter (eine "Bequemlichkeitsklasse") erbt, wird eine Methode des WindowListener-Interfaces überschrieben.
Die Klammersetzung dient der besseren Lesbarkeit.
Natürlich kann man es auch so schreiben, dann ist wieder zu erkennen, dass es eigentlich eine Anweisung ist:

```
addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } });
```


----------



## Leroy42 (3. Jun 2006)

Es handelt sich um eine innere, anonyme Klassendefinition
mit gleichzeitiger Instanzerzeugung und Übergabe dieser Instanz.

 :shock: 

Ich klabüser das mal auseinander.


```
class MeineErweiterungVonWindowAdapterDieIchNurEinmalBrauche extends WindowAdapter {
  public void windowClosing(WindowEvent e) {
    System.exit(0);
  }
}
```
wäre die übliche Klassendefinition.


```
void init() {
   ...
   WindowAdapter wappi = new MeineErweiterungVonWindowAdapterDieIchNurEinmalBrauche extends WindowAdapter();

  addWindowListener(wappi);
}
```
wäre die übliche Erzeugung einer Instanz und dessen Übergabe an die Methode addWindowListener()


```
addWindowListener(new WindowAdapter() {
       public void windowClosing(WindowEvent e) {
          System.exit(0);
       }});
```
ist die Abkürzung für uns schreibfaule Entwickler.

Zugegeben: Diese Syntax ist am Anfang wirklich gewöhnungsbedürftig. :autsch:


----------

