eigenständige Listener-Klasse

Hallo zusammen.

Bin Anfänger in Java und schlage mich dementsprechend mit einem Anfänger-Problem herum.

Bis jetzt verzichtete ich auf Eclipse und schrieb alles in einem einfachen Editor (Textpad oder Wordpad).
Ich finde das zum Lernen der Sprache vorteilhaft, da mir Eclipse zu viele Sachen automatisch macht, welche ich dann noch nicht richtig verstehe.


Im Allgemeinen geht es um die Hierarchie von Klassen und dem Zugriff auf Instanzen von einer Klasse zur Anderen.

In einem Projekt möchte ich der Übersicht halber meine Listener selber, in separaten Klassen schreiben.
Somit benutze ich keine anonymen ad hoc Listener, und die geschriebenen Listener-Klassen sollen keine inneren Klassen der Gui-Klasse sein.

Solange ich meine Listener-Klassen als innere Klasse vom Gui schreibe, funktioniert alles wunderbar.
Dadurch wird aber der Programm-Code lang und unübersichtlich.
Mache ich die Listener-Klassen zu eigenständigen, wirds problematisch.

Ich gehe dabei folgendermassen vor:

Ich habe eine "Starter"-Klasse, welche nur die Main-Methode enthält.
Dort instanziere ich ein Gui-Objekt (JFrame) und mache es sichtbar.
Z.B: Gui fenster = new Gui("blabla");

Meine Gui-Klasse erbt von JFrame.
Im Konstruktor der Gui-Klasse baue ich dann die graphische Oberfläche auf, JPanels, JButtons, JLabels etc.
Dort instanziere ich auch meine Listener-Objekte und adde sie den entsprechenden Elementen zu.

Z.B.:

MeinSchalterListener druck1 = new MeinSchalterListener();
button1.addActionListener(druck1);


Neben dem Konstruktor enthält die Gui-Klasse noch die Getter und Setter-Methoden.

So weit so gut.
Das Gui steht, die Listener sind aktiv.
Wie kann ich jetzt aber in den Performer-Methoden der Listener auf die Instanzen / Methoden der Gui-Klasse zugreifen?
Die Instanz "fenster" ist aus den Listener-Methoden heraus nicht sichtbar.
Ich kann weder auf Gui-Elemente (wenn ich das Kapselung-Prinzip ignoriere), noch auf Getter und Setter der Gui-Klasse zugreifen, was kein Problem ist, solange die Lister-Klassen innere der Gui-Klassen sind.

Allgemein formuliert:
Wie können bei zwei eigenständigen Klassen die Methoden der einen auf die Instanzen der anderen zugreifen und das in beide Richtungen?
Ich konnte das nur realisieren, wenn beide Klassen innere Klassen einer äusseren Klasse waren.

Hoffe, dass das Problem auch ohne Code verständlich formuliert ist...
Bedanke mich für die Antworten
 

pl4gu33

Top Contributor
du kannst der Listener- Klasse im Konstruktor ein Objekt der GUI Klasse mitgeben, wenn du ihn in der Klasse eh initalisiertst .zb. so:

GUI Klasse:

Java:
...
MeinSchalterListener druck1 = new MeinSchalterListener(this);
...

dann kannst du in der Listenerklasse auf die Getter/Setter der GUI Klasse zugreifen
 

JCODA

Top Contributor
Wie können bei zwei eigenständigen Klassen die Methoden der einen auf die Instanzen der anderen zugreifen und das in beide Richtungen?


Ganz allgemein: Indem man dem erzeugten Objekt eine Referenz auf die bestehende Instanz der anderen Klasse übergibt.

In deinem Fall geht es auch ein bisschen einfacher:
Code:
public void setActionCommand(String actionCommand)
AbstractButton (Java 2 Platform SE v1.4.2))
und mit
Code:
public String getActionCommand()
ActionEvent (Java 2 Platform SE v1.4.2))
 

Michael...

Top Contributor
Wie können bei zwei eigenständigen Klassen die Methoden der einen auf die Instanzen der anderen zugreifen und das in beide Richtungen?
Für die Entwicklung von Applikationen mit GUI sollte man meiner Meinung sich vorher mit den Grundlagen recht sicher sein. Dein Problem ist ein recht allgemein verbreitetes Anfängerproblem. Eine einfache Antwort: Die Objekte dieser Klassen müssen (z.B. in einer Instanzvariable) eine Referenz auf das jeweils andere Objekt besitzten. "Jemand" erzeugt Objekt A und Objekt B und übergibt dann beiden eine Referenz auf das andere Objekt.
Allerdings ist der direkte beidseitige Zugriff oftmals unnötig und erhöht dazu auch noch die Abhängigkeit beider Klassen untereinander. Vor allem bei der GUI Entwicklung verwendet man dazu verschiedene Entwurfsmuster, ein bekanntes ist z.B. das MVC Model View Controller ? Wikipedia Hiermit können die einzelnen Elemente recht lose miteinander gekoppelt und recht unabhängig von einander entwickelt werden.

Aber grundsätzlich spricht nichts gegen ananoyme innere Listener, da man oftmals ohnehin nicht im weiteren Codeverlauf auf diese zugreifen muss. Inwiefern der Code dadurch länger und unübersichtlicher wird, kann ich jetzt auf Anhieb nicht nachvollziehen.
 
Bin mir schon bewusst, dass ich Anfänger-Probleme mit OOP habe.
Wird halt von der Schule erwartet, sich in GUIs zu stürzen ohne gut fundierte OOP-Kenntnisse zu haben. (Werden auch keine geliefert)
Die Idee dabei, separate Listener-Klassen zu machen ist, dass ich jede Klasse in einem separaten File speichern kann, und sich dadurch den Code-Umfang pro File reduziert und überschaubarer wird.

Bin noch nicht sicher, ob ich richtig verstanden wurde, oder ob ich ein Brett vor dem Kopf hab...
Habe darum ein kleines Demo-Programm geschrieben:

Ein Gui mit 4 JButtons, die jeweils mit einem Listener verknüpft werden.
1. anonymer ad hoc Listener+Performer
2. anonymer Listener
3. eigener Listener aus innerer Klasse
4. eigener Listener aus separater Klasse

1-3 funktioniert
Bei 4 habe ich keine Referenz auf das Gui, kann JButton nicht umfärben.
Wie kriege ich für Listener 4 eine Referenz auf das Objekt fenster?



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

class Gui extends JFrame implements ActionListener{
	Color schwarz;
	Color weiss;
	Color rot;

	JPanel  container;
	JButton schalter1;
	JButton schalter2;
	JButton schalter3;
	JButton schalter4;

	//Konstruktor
	Gui(String titel){
		super(titel);
		setLayout(null);

		schwarz		= new Color(0, 0, 0);
		weiss		= new Color(255, 255, 255);
		rot			= new Color(255, 0, 0);
		container 	= new JPanel();
		schalter1	= new JButton("Schalter 1");
		schalter2	= new JButton("Schalter 2");
		schalter3	= new JButton("Schalter 3");
		schalter4	= new JButton("Schalter 4");

		container.setLayout(null);
		container.setBackground(weiss);
		container.setBounds(0, 0, 700, 300);
		add(container);

		schalter1.setBounds(50, 50, 100, 50);
		schalter1.setBackground(rot);
		container.add(schalter1);

		schalter2.setBounds(200, 50, 100, 50);
		schalter2.setBackground(rot);
		container.add(schalter2);

		schalter3.setBounds(350, 50, 100, 50);
		schalter3.setBackground(rot);
		container.add(schalter3);

		schalter4.setBounds(500, 50, 100, 50);
		schalter4.setBackground(rot);
		container.add(schalter4);

		//Listener + Performer ad hoc, anonym für Schalter 1
		schalter1.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e){
				System.out.println("Schalter 1 gedrueckt");
				schalter1.setBackground(schwarz);
			}
		});


		//anonymer Listener für Schalter 2
		schalter2.addActionListener(this);


		//Listener aus eigener innerer Klasse für Schalter 3
		schalter3.addActionListener(new Lauscher3());

		//Listener aus eigener separater Klasse für Schalter 4
		schalter4.addActionListener(new Lauscher4());


		setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
	}



	//Action Performer für Schalter 2
	public void actionPerformed(ActionEvent e){
		System.out.println("Schalter 2 gedrueckt");
		schalter2.setBackground(schwarz);
	}



	//eigene innere Klasse mit Action Performer für Schalter 3
	class Lauscher3 implements ActionListener{
		public void actionPerformed(ActionEvent e){
			System.out.println("Schalter 3 gedrueckt");
			schalter3.setBackground(schwarz);
		}
	}
}


//eigene separate Listener Klasse für Schalter 4
class Lauscher4 implements ActionListener{
	public void actionPerformed(ActionEvent e){
		System.out.println("Schalter 4 gedrueckt");

//*** geht nicht, kein Zugriff ****************************
//
//		fenster.schalter4.setBackground(fenster.schwarz);
//
//*********************************************************

	}
}

public class Starter{
	public static void main(String[]args){
		Gui fenster = new Gui("Gui");
		fenster.setBounds(600, 100, 700, 300);
		fenster.setVisible(true);
		fenster.container.setBackground(fenster.weiss);
	}
}
 

Landei

Top Contributor
[c]class Gui extends JFrame implements ActionListener[/c]

Das-kannste-schon-so-machen,-aber-dann-isses-halt-.png


Erst einmal finde ich es nicht gut, einen "globalen" Listener zu haben. Zum einen braucht dieser Listener wieder unnötigen, länglichen Code, um herauszufinden, welches Knöpfchen denn jetzt gedrückt wurde. Zum andern gibt es nicht nur ActionListener, sondern du endest mit einer Klasse, die ActionListenern, ItemListener, KeyListener und OmaHatIhrGebissVerlegtListener implementiert. Mit anderen Worten: Der Ansatz sieht für kleine Projekte attraktiv aus, "skaliert" aber nicht, wenn es komplizierter wird.

Dann sollte man auch nicht ohne Not JFrame erweitern. Das ist in Ordnung, wenn man neue Fenster-Funktionalität (etwa einen blinkenden Rahmen oder einen Titel in Laufschrift) hinzufügt, aber das tust du nicht - du benutzt nur ein Fenster, in dem du es konfigurierst und Inhalte einfügst, aber du erweiterst nicht das Konzept eines Fensters, du schaffst keine neue Art von Fenster - es ist immer noch ein stinknormales JFrame. Zu entscheiden, wann Vererbung und wann Komposition das richtige ist, ist eine Kunst, aber ich kann in diesem Fall fünfzehn Jahre Programmiererfahrung dafür in die Waagschale werfen, dass hier Vererbung fehl am Platze ist.

Wenn du eine separate Klasse GUI (ohne extends JFrame) hast, erzeugst du darin ein neues JFrame, und eventuell auch separate Listener, denen du die Referenz auf das JFrame oder andere Teile mitgeben kannst. Das JFrame und seine Komponenten sollten immer so "dumm" wie möglich sein - sie sollen etwas anzeigen, nichts berechnen.
 
Zuletzt bearbeitet:

Michael...

Top Contributor
Bei 4 habe ich keine Referenz auf das Gui, kann JButton nicht umfärben. Wie kriege ich für Listener 4 eine Referenz auf das Objekt fenster?
Eigentlich gibt es nur zwei (relevante) Möglichkeiten eine Referenz auf ein Objekt zu bekommen. Entweder man übergibt die Referenz direkt im Konstruktor oder zu einem späteren Zeitpunkt per Methode.
Hier mal ein Beispiel mit drei verschiedenen Varianten, in einem "externen" Listener auf den auslösenden Button zu zugreifen. Eine Referenz auf den Button ist übrigens auch im ActionEvent enthalten.
Java:
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.event.*;

import javax.swing.*;
 
public class Gui extends JFrame implements ActionListener{
    private JButton[] schalter;
    private int anzahlSchalter = 4;
 
    //Konstruktor
    Gui(String titel){
        super(titel);
        
        schalter = new JButton[anzahlSchalter];
        
        JPanel panel = new JPanel(new GridLayout(1, schalter.length, 30, 0));
        this.add(panel);
        panel.setBorder(BorderFactory.createEmptyBorder(80, 20, 80, 20));
        panel.setBackground(Color.WHITE);
        
        for (int i=0; i < schalter.length; i++) {
        	schalter[i] = new JButton("Schalter " + (i+1));
        	schalter[i].setBackground(Color.RED);
        	panel.add(schalter[i]);
        }

        //Dies ist kein anonymer Listener.
        //Hier wird der ActionListener "Gui" zugewiesen
        schalter[0].addActionListener(this);
        
        //externe Klassen als Listener
        schalter[1].addActionListener(new LauscherVariante1());
        schalter[2].addActionListener(new LauscherVariante2(schalter[2]));
        schalter[3].addActionListener(new LauscherVariante3(this));
    }
    
    public JButton getButton() {
    	return schalter[3];
    }
 
    public void actionPerformed(ActionEvent e){
    	System.out.println(e.getActionCommand() +" gedrueckt");
        schalter[0].setBackground(Color.BLACK);
    }
    
    public static void main(String[]args){
        Gui fenster = new Gui("Gui");
        fenster.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        fenster.setBounds(600, 100, 700, 300);
        fenster.setVisible(true);
    }
}
 
class LauscherVariante1 implements ActionListener{
    public void actionPerformed(ActionEvent e){
    	System.out.println(e.getActionCommand() +" gedrueckt");
    	JButton button = (JButton)e.getSource();
    	button.setBackground(Color.BLACK);
    }
}

class LauscherVariante2 implements ActionListener{
	private JButton button;
	
	public LauscherVariante2(JButton button) {
		this.button = button;
	}
	
    public void actionPerformed(ActionEvent e){
    	System.out.println(e.getActionCommand() +" gedrueckt");
    	button.setBackground(Color.BLACK);
    }
}

class LauscherVariante3 implements ActionListener{
	private Gui gui;
	
	public LauscherVariante3(Gui gui) {
		this.gui = gui;
	}
	
    public void actionPerformed(ActionEvent e){
    	System.out.println(e.getActionCommand() +" gedrueckt");
    	gui.getButton().setBackground(Color.BLACK);
    }
}
 

Landei

Top Contributor
Eigentlich gibt es nur zwei (relevante) Möglichkeiten eine Referenz auf ein Objekt zu bekommen. Entweder man übergibt die Referenz direkt im Konstruktor oder zu einem späteren Zeitpunkt per Methode.

Ich weiß nicht, ob das das jetzt "relevant" ist, aber man kann sich eine Referenz auch von einem DI-Framework (Spring, Guice) injizieren lassen, über das Service Provider Interface Implementierungen suchen oder einen Stream o.ä. deserialisieren. Gibt sicher noch mehr Möglichkeiten...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
G Datenaustausch JFrame und eigenständige JTable? Java Basics - Anfänger-Themen 2
T Variable durch Action Listener ändern Java Basics - Anfänger-Themen 2
D String value change listener Java Basics - Anfänger-Themen 2
topi WindowAdapter / Listener / Event Java Basics - Anfänger-Themen 4
L Problem mit Listener Java Basics - Anfänger-Themen 0
P Listener registrieren Java Basics - Anfänger-Themen 40
Salo JTabel Selection listener Bsp. Java Basics - Anfänger-Themen 3
W JLabel, Farbe durch Listener ändern Java Basics - Anfänger-Themen 6
M Listener für Button - Wert von Variablen verändern Java Basics - Anfänger-Themen 14
V JTable welcher Listener ? Java Basics - Anfänger-Themen 7
J Verständnis Problem Java-Listener. Java Basics - Anfänger-Themen 59
M Compiler-Fehler Using action listener Java Basics - Anfänger-Themen 1
F Listener schreiben Java Basics - Anfänger-Themen 1
P Eigene Knöpfe mit eigenem Listener Java Basics - Anfänger-Themen 5
B Listener beim Laden (deserialize) wieder hinzufügen bzw. mitspeichern? Java Basics - Anfänger-Themen 3
J Listener Java Basics - Anfänger-Themen 4
kaoZ Best Practice Verständnisfrage Listener bei lokalen Objekten Java Basics - Anfänger-Themen 8
F eigenes Listener Pattern mit Interface Java Basics - Anfänger-Themen 1
llabusch Kombinationsfeld - LISTENER Java Basics - Anfänger-Themen 0
S Eigenen Listener zu eigenen Button! Java Basics - Anfänger-Themen 5
S Listener reagieren nicht mehr Java Basics - Anfänger-Themen 3
O Laufender Timer+Action Listener in Thread VS isAlive() Java Basics - Anfänger-Themen 4
E Mein eigener Listener (Hilfe gesucht) Java Basics - Anfänger-Themen 2
K On Click listener Problem Java Basics - Anfänger-Themen 4
L JTextField/Listener Input Problem Java Basics - Anfänger-Themen 2
M Listener einerm JPanel hinzufuegen Java Basics - Anfänger-Themen 3
G Listener ohne Objekt Java Basics - Anfänger-Themen 5
T Button Text mit Action Listener [Hilfe!] Java Basics - Anfänger-Themen 10
H Eigenen Listener einbauen Java Basics - Anfänger-Themen 5
K Key Listener bei 2 gleichzeitig gedrückten tasten Java Basics - Anfänger-Themen 3
M Bäume und Listener Java Basics - Anfänger-Themen 2
K Erste Schritte table Listener noob frage Java Basics - Anfänger-Themen 3
T Motion listener Java Basics - Anfänger-Themen 10
U Listener erstellen Java Basics - Anfänger-Themen 16
N Variablen aus Action Listener lesen und weiterverarbeiten Java Basics - Anfänger-Themen 12
M listener Java Basics - Anfänger-Themen 16
L Listener Problem in Klasse Java Basics - Anfänger-Themen 8
P Listener für mehrere Buttons Java Basics - Anfänger-Themen 3
L Window Listener Java Basics - Anfänger-Themen 2
Kenan89 JTable: Listener Java Basics - Anfänger-Themen 4
N Klassen auf den Action Listener in einer andere Klasse zugreifen Java Basics - Anfänger-Themen 6
A action listener Java Basics - Anfänger-Themen 8
M Netbeans Listener - Anonymous, inner class, main class? Java Basics - Anfänger-Themen 4
K Action Listener reagiert nicht auf Button druck mehr??? Java Basics - Anfänger-Themen 4
E Mehrere Listener auf einen Button? Java Basics - Anfänger-Themen 3
P Input/Output InputStream Listener? Java Basics - Anfänger-Themen 7
X Problem bezüglich Key Listener Java Basics - Anfänger-Themen 3
Y Button hört nicht auf Listener Java Basics - Anfänger-Themen 5
H JTable, Listener und CellEditor Java Basics - Anfänger-Themen 8
H Listener und Events entfernen Java Basics - Anfänger-Themen 2
B OOP Eigener Event-Listener erstellen Java Basics - Anfänger-Themen 4
M Listener Objekte Java Basics - Anfänger-Themen 12
S Applet Key Listener Java Basics - Anfänger-Themen 6
J Action Listener Java Basics - Anfänger-Themen 2
G Probleme mit Listener Java Basics - Anfänger-Themen 27
B Wert einer Variable mit Listener ueberwachen Java Basics - Anfänger-Themen 3
F Port Listener Java Basics - Anfänger-Themen 9
J JComboBox Listener Java Basics - Anfänger-Themen 6
J Window-Listener funktionieren nicht Java Basics - Anfänger-Themen 7
N Frage zu Listener für Textfelder Java Basics - Anfänger-Themen 5
Benji0815 Eigenen Listener schreiben Java Basics - Anfänger-Themen 13
M Probleme beim Aufruf von Listener in anderer Klasse Java Basics - Anfänger-Themen 9
S Key-Listener richtig "einbauen" Java Basics - Anfänger-Themen 42
S Listener von ausserhalb aufrufen Java Basics - Anfänger-Themen 2
S Action Listener Java Basics - Anfänger-Themen 6
Sweety Listener in Swing Java Basics - Anfänger-Themen 8
Hamstinator Design und Listener in verschiedenen Klassen Java Basics - Anfänger-Themen 6
Developer_X Mouse MOTION listener example Java Basics - Anfänger-Themen 5
J Mouse-Listener Java Basics - Anfänger-Themen 3
I Listener Klassen in Package Java Basics - Anfänger-Themen 3
StickToFreak Applet -> GameLoop + Listener / Listener funktioniert nicht Java Basics - Anfänger-Themen 22
B externer Listener für Zeichenbereich? Java Basics - Anfänger-Themen 2
D dialog listener? Java Basics - Anfänger-Themen 2
G Key Listener arbeitet Fehlerhaft Java Basics - Anfänger-Themen 6
C Listener und Events Java Basics - Anfänger-Themen 10
E Listener Java Basics - Anfänger-Themen 2
hdi keylistener hat keinen fokus oder: listener ohne frame? Java Basics - Anfänger-Themen 10
G jtable listener wenn zeile markiert wird Java Basics - Anfänger-Themen 6
S Action Listener Funktioniert nicht Java Basics - Anfänger-Themen 6
D Kombinationsfeld => Realisierung im Listener? Java Basics - Anfänger-Themen 2
G LIstener bei JavaMail Java Basics - Anfänger-Themen 2
G Context Listener des Apache Tomcat verwenden Java Basics - Anfänger-Themen 4
D Listener bzw. Interfaces Java Basics - Anfänger-Themen 7
A Wo/Wie Event Listener Java Basics - Anfänger-Themen 3
G Window Listener? Java Basics - Anfänger-Themen 2
G 2 Listener wiedersprechen sich. Java Basics - Anfänger-Themen 12
G Listener für JPanel für Statusmeldungen Java Basics - Anfänger-Themen 3
F Listener für Variable Java Basics - Anfänger-Themen 29
A Gibt es standardmässig in Java einen Verzeichnis-Listener? Java Basics - Anfänger-Themen 6
N Listener für datei Java Basics - Anfänger-Themen 13
S Mit Listener AWT Objekte ansprechen Java Basics - Anfänger-Themen 2
G listener für radiobutton Java Basics - Anfänger-Themen 1
G Listener Java Basics - Anfänger-Themen 5
G Listener Problem Java Basics - Anfänger-Themen 3
B Wiso funktioniet das nicht? (Listener) Java Basics - Anfänger-Themen 6
H Key Listener macht nicht das was er soll Java Basics - Anfänger-Themen 4
T Wartet Klasse auf Listener? Java Basics - Anfänger-Themen 3
D Listener? Java Basics - Anfänger-Themen 2
S Listener auf JTextfeld Java Basics - Anfänger-Themen 8
B Kommunikation zwischen Klasse und Listener Java Basics - Anfänger-Themen 2

Ähnliche Java Themen

Neue Themen


Oben