Wie reagiert ein Button beim Anklicken?

Schaltflächen wie JButton erzeugen bei Benutzung, wie viele andere Komponenten auch, sog. events (Ereignisse). Je nach Komponente werden unterschiedliche Ereignisse ausgesandt. Bei Schaltflächen ist dies ein ActionEvent.

Da man normalerweise nicht an allen ausgesandten Ereignissen interessiert ist, muss man diejenigen, auf die man reagieren möchte, abfangen. Hierzu steht für jedes spezielle Ereignis ein sog. Listener zur Verfügung, bei dem man die das Ereignis erzeugende Komponente anmelden muss.
In den folgenden drei Beispielen werden hierzu die gängigsten Verfahren anhand einer einfachen Schaltfläche vorgestellt, die bei Betätigung einen kurzen Text auf der Konsole ausgeben soll.
Der ActionListener selbst ist eine Schnittstelle mit einer Methode, void actionPerformed(ActionEvent e), die von der interessierten Klasse implementiert werden muss.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;

public class ButtonEventClass extends JFrame implements ActionListener {
    
    private JButton button;
    
    public ButtonEventClass(){
        button = new JButton("click mich!");
        button.addActionListener(this);
        
        this.getContentPane().add(button);
    }
    
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button){
            System.out.println("Button geklickt!");
        }
    }
    
    public static void main(String[] args){
        ButtonEventClass bec = new ButtonEventClass();
        bec.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        bec.setSize(200, 200);
        bec.setVisible(true);
    }
}

Im ersten Beispiel implementiert die Klasse, die den Button enthält, den Listener selber. Somit muss sie selbst die Methode actionPerformed() enthalten, die als Parameter ein ActionEvent übergeben bekommt.
Der Ereignisauslöser muss jetzt durch die Methode addActionListener()mit dem Listener verbunden werden. Als Parameter wird ein Verweis auf das aktuelle Objekt der eigenen Klasse übergeben, da die Klasse ja selbst den Listener implementiert.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;

public class ButtonEvent2Class extends JFrame {
    
    private JButton button;
    
    public ButtonEvent2Class(){
        button = new JButton("click mich!");
        button.addActionListener(new ButtonLauscher());
        
        this.getContentPane().add(button);
    }
    
    class ButtonLauscher implements ActionListener {
        public void actionPerformed(ActionEvent e) {
            if(e.getSource() == button){
                System.out.println("Button geklickt!");
            }
        }
    }
    
    public static void main(String[] args){
        ButtonEvent2Class bec = new ButtonEvent2Class();
        bec.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        bec.setSize(200, 200);
        bec.setVisible(true);
    }
}

Im zweiten Beispiel wird der ActionListener in einer eigenen inneren Klasse realisiert, von der eine Instanz mit dem Button verbunden wird. Wie im ersten Beispiel auch kann mit der Methode ActionEvent.getSource() die Ereignisquelle ermittelt werden. Auf diese Weise kann ein Listener mehrere Ereignisse überwachen.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;

public class ButtonEvent3Class extends JFrame {
    
    private JButton button;
    
    public ButtonEvent3Class(){
        button = new JButton("click mich!");
        button.addActionListener(new ButtonLauscher());
        
        this.getContentPane().add(button);
    }
    
    
    
    public static void main(String[] args){
        ButtonEvent3Class bec = new ButtonEvent3Class();
        bec.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        bec.setSize(200, 200);
        bec.setVisible(true);
    }
}

class ButtonLauscher implements ActionListener {
    public void actionPerformed(ActionEvent e) {
            System.out.println("Button '" + ((JButton)e.getSource()).getText() + "' geklickt.");
    }
}

Das dritte Beispiel entspricht in den Grundzügen dem zweiten. Jedoch ist der Listener nicht als innere, sondern als selbstständige Klasse realisiert. Da hier die Instanz des auslösenden JButton nicht mehr zur Verfügung steht, ist ein Abgleich mit

if(e.getSource() == button){ //...

wie in Beispiel 2 so nicht mehr möglich. Die Lösung zeigt die Version 4. In dieser wird der Listener-Klasse das Objekt des auslösenden Buttons als Parameter übergeben und im Konstruktor an eine Instanzvariable weitergeleitet. Diese kann dann auf die bekannte Weise abgefragt werden.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;

public class ButtonEvent4Class extends JFrame {
    
    private JButton button;
    
    public ButtonEvent4Class(){
        button = new JButton("click mich!");
        button.addActionListener(new ButtonLauscher4(button));
        
        this.getContentPane().add(button);
    }
    
    
    
    public static void main(String[] args){
        ButtonEvent4Class bec = new ButtonEvent4Class();
        bec.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        bec.setSize(200, 200);
        bec.setVisible(true);
    }
}

class ButtonLauscher4 implements ActionListener {
    JButton button;
    public ButtonLauscher4(JButton button){
        this.button = button;
    }
    public void actionPerformed(ActionEvent e) {
        if(e.getSource() == button)
            System.out.println("Button '" + ((JButton)e.getSource()).getText() + "' geklickt.");
    }
}