Wie findet man heraus, welche Component einen Event ausgelöst hat?
Wenn man mehrere Components erstellt, die eine “ähnliche” Funktion besitzen, möchte man sie häufig gleich behandeln. Trotzdem muss man wissen, von welcher Component ein Event stammt, den man behandeln will. Es gibt für dieses Problem im wesentlichen zwei verschiedene Lösungsansätze. Diese werden hier am Beispiel von Buttons und ActionEvents kurz beschrieben. Man kann sie aber leicht auf andere Components und Events übertragen.
- Möglichkeit:
Man verwendet einen einzigen Listener (genauer: nur eine Instanz eines Listeners) für alle Components. In der Methode, die den Event behandelt (z.B. in actionPerformed) muss man dann abfragen, von welcher Component der Event ausgelöst wurde. Am einfachsten geht das, indem man mit event.getSource() die Quelle des Events abfragt:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class ButtonsFAQ01a extends JFrame implements ActionListener
{
public static void main(String args[])
{
new ButtonsFAQ01a();
}
// Die Buttons in dieser Klasse
private JButton button0;
private JButton button1;
private JButton button2;
// Erstellt diesen Frame und fügt das Panel mit den Buttons hinzu
public ButtonsFAQ01a()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,100);
getContentPane().add(createButtonsPanel());
setVisible(true);
}
// Erzeugt ein Panel, das die Buttons enthält
private JPanel createButtonsPanel()
{
JPanel buttonsPanel = new JPanel(new GridLayout(1,0));
// Erstelle die Buttons
button0 = new JButton("button0");
button1 = new JButton("button1");
button2 = new JButton("button2");
// Füge 'this' als ActionListener zu allen Buttons hinzu
button0.addActionListener(this);
button1.addActionListener(this);
button2.addActionListener(this);
// Lege die Buttons in das Panel
buttonsPanel.add(button0);
buttonsPanel.add(button1);
buttonsPanel.add(button2);
return buttonsPanel;
}
// Wird aufgerufen, wenn irgendeiner der Buttons geklickt wurde
public void actionPerformed(ActionEvent event)
{
// ßberprüfe, welcher der Buttons die Quelle des Events war
if (event.getSource() == button0)
{
System.out.println("button0");
button0.setEnabled(false);
}
else if (event.getSource() == button1)
{
System.out.println("button1");
button1.setEnabled(false);
}
else if (event.getSource() == button2)
{
System.out.println("button2");
button2.setEnabled(false);
}
}
}
Häufig liegen die Components, um die es geht, in einem Array. In diesem Fall kann man das Erzeugen der Components, und die Abfrage, von welcher Component der Event ausgelöst wurde, in einer Schleife machen:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class ButtonsFAQ01b extends JFrame implements ActionListener
{
public static void main(String args[])
{
new ButtonsFAQ01b();
}
// Die Buttons in dieser Klasse
private JButton buttons[];
// Erstellt diesen Frame und fügt das Panel mit den Buttons hinzu
public ButtonsFAQ01b()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,100);
getContentPane().add(createButtonsPanel());
setVisible(true);
}
// Erzeugt ein Panel, das die Buttons enthält
private JPanel createButtonsPanel()
{
JPanel buttonsPanel = new JPanel(new GridLayout(1,0));
// Erstelle die Buttons, füge 'this' als ActionListener zu allen
// Buttons hinzu, und lege die Buttons in dieses Panel
buttons = new JButton[3];
for (int i=0; i<buttons.length; i++)
{
buttons** = new JButton("button"+i);
buttons**.addActionListener(this);
buttonsPanel.add(buttons**);
}
return buttonsPanel;
}
// Wird aufgerufen, wenn irgendeiner der Buttons geklickt wurde
public void actionPerformed(ActionEvent event)
{
// ßberprüfe, welcher der Buttons die Quelle des Events war
for (int i=0; i<buttons.length; i++)
{
if (event.getSource() == buttons**)
{
System.out.println("button["+i+"]");
buttons**.setEnabled(false);
}
}
}
}
Wenn die Components in einer Liste liegen, kann man statt der Schleife auch die Methode ‘List#indexOf’ verwenden:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
class ButtonsFAQ01c extends JFrame implements ActionListener
{
public static void main(String args[])
{
new ButtonsFAQ01c();
}
// Die Buttons in dieser Klasse
private List<JButton> buttons;
// Erstellt diesen Frame und fügt das Panel mit den Buttons hinzu
public ButtonsFAQ01c()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,100);
getContentPane().add(createButtonsPanel());
setVisible(true);
}
// Erzeugt ein Panel, das die Buttons enthält
private JPanel createButtonsPanel()
{
JPanel buttonsPanel = new JPanel(new GridLayout(1,0));
// Erstelle die Buttons, füge 'this' als ActionListener zu allen
// Buttons hinzu, und lege die Buttons in dieses Panel
buttons = new ArrayList<JButton>();
for (int i=0; i<3; i++)
{
JButton button = new JButton("button"+i);
buttons.add(button);
button.addActionListener(this);
buttonsPanel.add(button);
}
return buttonsPanel;
}
// Wird aufgerufen, wenn irgendeiner der Buttons geklickt wurde
public void actionPerformed(ActionEvent event)
{
// Überprüfe, welcher der Buttons die Quelle des Events war
int index = buttons.indexOf(event.getSource());
System.out.println("button["+index+"]");
buttons.get(index).setEnabled(false);
}
}
- Möglichkeit:
Man verwendet anonyme Listener, die jeweils nur auf eine Component hören. Der Vorteil dabei ist die höhere Flexibilität, und dass man nicht die Quelle des Events abfragen muss: Jeder Listener kennt automatisch “seine” Component.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
class ButtonsFAQ02 extends JFrame
{
public static void main(String args[])
{
new ButtonsFAQ02();
}
// Erstellt diesen Frame und fügt das Panel mit den Buttons hinzu
public ButtonsFAQ02()
{
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300,100);
getContentPane().add(createButtonsPanel());
setVisible(true);
}
// Erzeugt ein Panel, das die Buttons enthält
private JPanel createButtonsPanel()
{
JPanel buttonsPanel = new JPanel(new GridLayout(1,0));
for (int i=0; i<3; i++)
{
// Erstelle den Button und merke dir den index 'i'
// Beides müssen 'final' Variablen sein, damit aus
// der anonymen inneren Klasse darauf zugegriffen
// werden kann.
final JButton button = new JButton("button"+i);
final int number = i;
// Füge einen anonymen ActionListener zu dem Button hinzu
button.addActionListener(new ActionListener()
{
// Wird aufgerufen, wenn der Button 'button' geklickt wurde
public void actionPerformed(ActionEvent event)
{
System.out.println("button"+number);
button.setEnabled(false);
}
});
buttonsPanel.add(button);
}
return buttonsPanel;
}
}
(Dieser Beitrag entspricht dem Beitrag aus dem java-forum.org. Dort war der Name des Autors entfernt - und dieser Autor war ursprünglich ich)