# ActionListener implementieren



## mmih (4. Dez 2006)

Hallo,

ich habe eine Klasse für eine GUI, die so aussieht:


```
import java.awt.*;
import java.awt.event.ActionEvent;
import java.net.URL;
import javax.swing.*;

class Spielanzeige
{
	private ImageIcon imageIcon;
	private JFrame f;
	private JLabel pic;
	private JLabel statusLine;
	private JList forbiddenWords;
	private LabelList forbiddenList;
	private JList triedWords;
	private LabelList triedList;
	private JTextField insertWord;
	private JButton okButton;
	private JLabel timeCounter;
	private JButton anotherPic;
	
	private Boolean init = false;
	
	protected void setImage( URL url )
	{
		imageIcon = new ImageIcon(url);
	}

	static void addComponent( Container cont, GridBagLayout gbl,
			Component c, int x, int y, int width, int height,
			double weightx, double weighty )
	{
		GridBagConstraints gbc = new GridBagConstraints();
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = x; gbc.gridy = y;
		gbc.gridwidth = width; gbc.gridheight = height;
		gbc.weightx = weightx; gbc.weighty = weighty;
		gbl.setConstraints( c, gbc );
		cont.add( c );
	}

public void createAndShowGUI()
	{
		LabelList forbiddenList = new LabelList();
		forbiddenList.addEntry( "verboten" );
		forbiddenList.addEntry( "illegal" );
		
		LabelList triedList = new LabelList();
		triedList.addEntry( "Versuch 1" );

		f = new JFrame();
		pic = new JLabel( imageIcon );
		statusLine = new JLabel( "Statuszeile" );
		forbiddenWords = new JList( forbiddenList.returnList() );
		triedWords = new JList( triedList.returnList() );
		insertWord = new JTextField();
		okButton = new JButton( "OK" );
		timeCounter = new JLabel( "Time" );
		anotherPic = new JButton( "anderes Bild" ); 

		f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
		Container c = f.getContentPane();
		GridBagLayout gbl = new GridBagLayout();


		c.setLayout( gbl );
		//													x	y	w	h	wx	 wy
		addComponent( c, gbl, pic,							0,	0,	1,	7,	600,	580 );
		addComponent( c, gbl, statusLine,					0,	8,	3,	1,	600,	20 );
		addComponent( c, gbl, new JLabel("Tabu-Wörter:"),	1,	0,	2,	1,	200,	20 );
		addComponent( c, gbl, forbiddenWords,				1,	1,	2,	1,	200,	210 );
		addComponent( c, gbl, new JLabel("Eingabewörter:"),	1,	2,	2,	1,	200,	20 );
		addComponent( c, gbl, triedWords,					1,	3,	2,	1,	200,	210 );
		addComponent( c, gbl, new JLabel("Wort"),			1,	4,	2,	1,	200,	20 );
		addComponent( c, gbl, insertWord,					1,	5,	1,	1,	150,	20 );
		addComponent( c, gbl, okButton, 					2,	5,	1,	1,	50,		20 );
		addComponent( c, gbl, new JLabel(""),				1,	6,	2,	1,	200,	20 );
		addComponent( c, gbl, timeCounter,					1,	7,	1,	1,	100,	20 );
		addComponent( c, gbl, anotherPic,					2,	7,	1,	1,	100,	20 );
		f.setSize( 800, 600 );
		f.setVisible( true );
		init = true;
	}
	
	protected void ActionPerformed( ActionEvent insertEntry)
	{
		triedList.addEntry( insertWord.getText() );
		triedWords = new JList( triedList.returnList() );
	}
}
```

Die Anzeige der Komponenten funktioniert auch bereits, allerdings bin ich damit überfordert diese Klasse um ActionListener für zunächst folgende Funktionen zu erweitern: wenn der OK-Button gedrückt wird oder im JTextField insertWord die Enter-Taste gedrückt wird soll triedList.addEntry() mit dem Eingabewort aus dem JTextField insertWord aufgerufen und anschließend das JTextField erneut geladen (also mit allen Änderungen) werden.

Wie ist das möglich?

Danke,
Martin


----------



## m@nu (4. Dez 2006)

deine klasse muss das ActionListener-interface implementieren...


```
public class Spielanzeige implements ActionListener {
//...
```
damit musst die die actionPerformed-methode implementieren (hast du bereits gemacht, jedoch wird das "A" klein geschrieben  )

dann kannst du beim initialisieren folgendes machen:

```
f.addActionListener(this);
```

voilà 
(die funktion die der actionlistener ausführen soll hab ich jetzt nicht angeschaut... aber da weist du ja was du haben willst  )


----------



## mmih (4. Dez 2006)

Den ActionListener habe ich zum OKButton hinzugefügt (der JFrame f verträgt scheinbar keinen ActionListener).

Die Methode actionPerformed wird auch aufgerufen, aber wie bekomme ich die JList aktualisiert?


----------



## WieselAc (4. Dez 2006)

am einfachsten wäre in dem fall wohl ein repaint() des Frames.


----------



## mmih (4. Dez 2006)

Das habe ich gemacht, leider wird das Fenster dennoch nicht wie gewünscht aktualisiert.

Ich habe den ganzen Ordner (ich arbeite derzeit mit Eclipse unter Windows) unter folgender URL als Archiv abgelegt: http://www.mmih.de/ESPGame/ESPGame.zip ).


----------



## m@nu (4. Dez 2006)

ach ja sry, stimmt, den listener musst du dem button hinzufügen  *shameOnMe*

warum erstellst du deine JList nach jedem klick neu?
am allereinfachsten nutzt du ein DefaultListModel.

```
public class Spielanzeige implements ActionListener {
  private DefaultListModel model = new DefaultListModel();
  //...
```


```
// Beim initialisieren deines Frames:
triedWords = new JList(model);
```


```
public void actionPerformed( ActionEvent insertEntry) 
   { 
      model.addElement(insertWord.getText()); 
   }
```

das DefaultListModel erweitert AbstractListModel, welches bereits alles nötige implementiert hat, um die JList über veränderungen im model zu informieren.

ps. such mal nach ListModel im google... du kannst dir auch ein eigenes ListModel basteln anstatt das DefaultListModel zu verwenden.


----------



## WieselAc (4. Dez 2006)

Stimmt das ist natürlich die eleganteste Lösung. 


Hier noch ein quick hack der ganz fies ist, aber meistens hilft:

Ganz brutal auf den Frame anwenden.


```
setVisilbe(false);
setVisilbe(true);
```


(Sollte man aber nitt machen. Nur wenn es schnell gehen muss)


----------



## mmih (4. Dez 2006)

Danke schon einmal für die bisherige Hilfe.

Ich habe zwischenzeitig noch Fehler in der LabelList gefunden und beseitigt. Desweiteren funktioniert jetzt auch das hinzufügen von Elementen zur Wortliste einwandfrei.

Aber ich habe immer noch Probleme mit dem "Kaffee": Wie kann ich die Eingabezeile nach Bestätigung löschen und die Statuszeile aktualisieren? Meine Ansätze in der ActionPerformed Methode (Spielanzeige.java) helfen mir leider nicht weiter. Vielleicht kann ich ja noch einen Tipp bekommen?

Danke,
Martin

PS: Der Source liegt aktuell unter der oben genannten URL. Es ist wahrscheinlich das einfachste, sich das gesamte Projekt ansehen zu können.


----------



## m@nu (4. Dez 2006)

```
insertWord.setText("");  // text löschen
statusLine.setText("Dein Status");
```

... oder nicht?


----------



## mmih (4. Dez 2006)

Hallo,

jetzt bin ich in folgener Situation:

ich habe einen zweiten ActionListener erstellt, mit dem ich ein neues Bild laden möchte. Dieser funktioniert auch einwandfrei, jedoch nur wenn der erste ActionListener auskommentiert ist. Wie schaffe ich es, dass ich beide aktiv haben kann?

Wie kann ich das Bild auf maximal 580 Pixel Höhe sowie 600 Pixel Breite (abhängig von der größten Seitenlänge) herunterzoomen, sofern dies erforderlich ist? (Wenn der ActionListener für das Bild aktiv ist wird mit Klick auf den Button ein übergroßes Bild geladen.)

Der Quellcode ist wieder unter der bereits genannten URL http://www.mmih.de/ESPGame/ESPGame.zip gespeichert.

Danke,
Martin


----------



## m@nu (5. Dez 2006)

du kannst pro klasse natürlich nur eine methode mit dem selben namen haben.
es gibt zwei möglichkeiten:

entweder du erstellst 2 innere klassen, welche beide einen ActionListener implementieren:

```
public class Spielanzeige {
//...

  public void createAndShowGUI() {
    //...
    okButton.addActionListener(new Listener1());
    anotherPic.addActionListener(new Listener2());
    //...
  }

  private class Listener1 implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
      // listener 1 code...
    }
  }

  private class Listener2 implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
      // listener 2 code...
    }
  }
}
```
(anstatt inneren klassen kannst du natürlich auch ne ganz normale klasse schreiben... gibt einfach wieder eine neue sourcedatei, welche für andere klassen nicht wirklich von nutzen sein werden, denk ich mal)


ich persönlich bevorzuge jedoch folgende variante (vorallem dann, wenn es sich um einen kleineren actionlistener handelt)

```
public class Spielanzeige {
  private JButton okButton;
  private JButton anotherPic;
  //...

  public void createAndShowGUI() {
    //...
    MyActionListener listener = new MyActionListener();
    okButton.addActionListener(listener);
    anotherPic.addActionListener(listener);
    //...
  }

  private class MyActionListener implements ActionListener {
    public void actionPerformed(ActionEvent ae) {
      Object source = ae.getSource();

      if(source.equals(okButton)) {
        // listener 1 code
      } else if(source.equals(anotherPic)) {
        // listener 2 code
      }
    }
  }
}
```

sind natürlich nur vorschläge... gibt noch zig andere möglichkeiten...


----------

