Auf ActionListener in anderer Klasse zugreifen?

Hallo,

ich möchte gerne auf den ActionListener zugreifen, dieser befindet ich aber in einer eigenen Klasse.


package Klassen;

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

import javax.swing.JButton;

public class Schaltflächen extends JButton implements ActionListener {
	
	public Schaltflächen(){
		
		this.setSize(70, 30);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		
			
      }
   }
}


Nun habe in der Main-Klasse 4 Buttons nach dieser Klasse erzeugt und wollte, wenn ein Button gedrückt wird das etwas passiert.
Nun frage ich mich wie ich nun auf den ActionListener zugreifen kann?

MfG

Dafür gibt es mehrere Möglichkeiten, je nach Anwendungsfall. Ich rate mal ein bisschen (wenn es nicht passt, zeige mal die andere Klasse):

package Klassen; //Packages sollten klein geschrieben werden

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

import javax.swing.JButton;

public class Schaltfläche extends JButton {
	
    public Schaltfläche(ActionListener al){
        this.setSize(70, 30);
        this.addActionListener(al);
    }
}

public class DieAndereKlasse {

   public DieAndereKlasse() {
        Schaltfläche schaltflache = new Schaltfläche(event -> 
                System.out.println("Hier könnte Ihre Funktionalität ausgeführt werden!")
        );
        //packe die Schaltfläche in dein Layout
   }
}

Eine Schöne Lösung ist auch, den Listenern ein passendes Objekt einer AbstractAction zu übergeben. Diese funktionieren überall dort, wo man ActionListener einsetzen würde.
Der Lohn für ein wenig mehr Arbeit ist eine sehr flexible Lösung die bspw. in JMenuItems, JButtons etc funktioniert.

Man erzeugt eine Klasse, die von AbstractAction erbt und implementiert dort die actionPerformed()-Methode:

import java.awt.event.*;
import javax.swing.*;

public class MyAction extends AbstractAction {
   public MyAction(String title) {
      super(title);
   }

   public void actionPerformed(ActionEvent e) {
      //was zu tun ist
   }
}

Das wäre die einfachste Variante. Ein Icon wäre auch möglich. Auch eine Verbindung zum Controller oder einer anderen Klasse, die von hier aus aufgerufen wird.

Für einen JButton würde man nun die Action so einbauen:

   JButton myButton = new JButton(new MyAction("Klick mich!"));

Fertig. Mehr ist nicht notwendig.

Wollte man die Funktion, die nun am JButton verfügbar ist für ein JMenuItem einsetzen wollen, würde das so aussehen:

   JMenuItem myMenuItem = new JMenuItem(new MyAction("Klick mich!"));

Mehr zum Thema findest du auch im Wiki-Artikel: JButton

public class ... implements ActionListener ist schon alleine darum blöd weil du dann genau einen ActionListener für alle Objekte dieser Klasse definierst - was man normalerweise nicht will (sonst muss man für jeden Button auch ne eigene Klasse schreiben). Und du willst auch nicht eine gemeinsame actionPerformed nur um in dieser nach source wieder zu unterscheiden (glaub mir, das willst du wirklich nicht weils nämlich Käse ist erst auszulagern, dann alles zusammenwerfen und wieder trennen).
Stichwort heißt hier (mit Lambdas noch schöner, aber ohne halt[noparse]:)[/noparse] innere anonyme Klassen in denen du für jeden Button genau definierst was er machen soll.

Hier ist die Main-Klasse:

package Klassen;

import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;


import javax.swing.JPanel;

public class HauptFenster {
	
	public static int high;
	public static int width;

	public static void main(String[] args) throws InterruptedException {
		
		Fenster fenster = new Fenster();
		Rechteck panel = new Rechteck();
		
		Schaltflächen up = new Schaltflächen();
		Schaltflächen down = new Schaltflächen();
		Schaltflächen left = new Schaltflächen();
		Schaltflächen right = new Schaltflächen();
		
		fenster.add(panel);
		
		fenster.add(up);
		fenster.add(down);
		fenster.add(left);
		fenster.add(right);
		
		
		while(true){
		
			high = (int)(Math.random()*200);
			width = (int)(Math.random()*150);
			
			panel.setx(high);
			panel.sety(width);
			
			System.out.println(high);
			
			fenster.repaint();
			
			Thread.sleep(10000);
			
		}
	}
		
}

Hier erzeuge ich einfach die Button-Objekte.
Hier wollte ich auch den Listener hinzufügen.
Da ich mir dachte, dass das ganze Übersichtlich sein sollte, mache ich eine eigene Klasse für die Buttons “Schaltfläche”.

Gut, und was willst du dann in deiner Klasse in dem einen ActionListener machen? Richtig: wieder mühsam rausfinden welcher Button denn jetzt der auslösende war. Das macht man nicht. Man baut keinen AllesListener nur um dann wieder alles aufzusplitten sondern added für jeden Button einen eigenen Listener der dann auch nur eine Aufgabe hat.

Das kann ich nur bestätigen, das habe ich bei meinem ersten Swing-Projekt ohne es besser zu wissen so gemacht und es ist einfach nur ein Krampf. Mit anonymen ActionListenern wird alles wesentlich dezentraler, übersichtlicher und verständlicher.
Und falls ich das Projekt nochmal refakturieren sollte, ist das eins der ersten Dinge, die dran glauben müssen…

Ja, ich glaube euch das auch, dass das übersichtlicher ist wenn man einzelne ActionListener verwendet.

Zuerst einmal muss ich aber Verstehen wie ich genau den ActionListener in meinen Sourcecode einfüge.
Hier habe ich probleme, da ich das nicht wirklich Verstanden habe.

Ich habe das bis jetzt immer so gemacht wie hier:

ActionEvent und ActionListener

PS: Dein Sourcecode hat nicht funktioniert.

Aus irgendeiner Gui von mir:

        showUrlButton.setFocusable(false);
        showUrlButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String url = urlField.getText().trim();
                if (!url.isEmpty()) {
                    logic.openLinkInBrowser(url);
                }
            }
        });```

public class ... extends JFrame implements ActionListener ist ganz evil. Gewöhn dir das gar nicht erst an - oder wenn schon zu spät: ganz schnell wieder vergessen. Das macht man nicht.

Zur Frage: Wie jeden anderen EventListener auch: someInstance.addXXXListener(someListenerInstance);
Alternative: someInstance.addXXXListener(new XXXListener(Event e) { /* code */ });
oder mit Lambda: someInstance.addXXXListener(e -> { /* code */ });

Dazu gehört dann aber auch noch die Erklärung, warum das nicht gemacht werden soll und wie man es richtig macht. Ansonsten ist dieser Satz wertlos.
Warum man nicht von JFrame/JDialog erben sollte - Byte-Welt-Wiki