ActionListener "nach oben weitergeben"

Samarek

Aktives Mitglied
Hi,
ich hab folgendes Problem, vielleicht gehört das sogar in's Anfängerforum, also ...
momentan baue ich eine Oberfläche auf, unter anderem aus selbstgemachten JPanels auf denen verschiedene Sachen stehen, die vielleicht verändert werden sollen und auf denen es Buttons gibt.

Jetzt möchte ich gerne das z.B. einer der Buttons ein Objekt das dem, alles beinhaltenden, JFrame gehört beeinflusst, also z.B. eine Methode von diesem Objekt aufruft, ihm einen Wert übergibt oder was auch immer.

Wie bringe ich also den ActionListener der auf dem JPanel liegt mit dem Objekt zusammen dass dem JFrame gehört, so dass ich also im ActionListeners des JPanels eine Methode des Objektes vom JFrame aufrufen kann.

... und das ganze soll natürlich auch den Geist der Verkapselung zufriedenstellen, also allgemein sein, so dass ich das gleiche selbstgemachte JPanel auch auf anderen JFrames benutzen kann.
 
Wenn ich das Getippse richtig verstanden habe, macht man das Umgekehrt.

Mach die "obere" Komponente zum Listenener und teil am Anfang der unteren Komponente mit wer Listener ist.
(Ob das MVC ist, weiss ich wirklich nicht)

Nicht lauffähiges Codeschnipsel:
Java:
import java.awt.event.*;

public class ObereKlasse implements ActionListener {

	UntereKlasse uk;

	public ObereKlasse() {
		uk = new UntereKlasse(this);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO Auto-generated method stub
	}

	public static void main(String... args) {
		ObereKlasse ok = new ObereKlasse();
	}
}

Java:
import java.awt.event.ActionListener;
import javax.swing.JButton;

public class UntereKlasse {

	private final ActionListener mActionListener;
	private JButton mButton;

	public UntereKlasse (ActionListener listener) {
		mActionListener = listener;
 		mButton = new JButton();
 		mButton.addActionListener(mActionListener);
	}
}
 
Java:
public void actionPerformed(ActionEvent e) 
{
  // Bau dir doch einen getter um an den Frame zu kommen.
  // Dabei muss der natürich nicht ne static methode sein, sondern kann auch an einem 
  // anderen Objekt abrufbar sein ;)
  MeinFrame frame = MeinFrame.holeBestehendesExemplar();
  // Danach mach etwas damit

}
 
Ja, das war beides schonmal sehr nützlich, danke dafür.

Aber jetzt kommt das ja alles in der gleichen actionPerformed an und das differenzieren der Buttons hier jetzt die Lösung sein soll kann ich mir nicht vorstellen.
Wie komme ich denn jetzt dahin dass der geklickte Button auch genau macht was er soll?
 
Also ich führe dazu mal das Modell von Andi_CH weiter:

Du musst ja in der actionPerformed-Methode mit is-Else-Abfragen immer rausfinden, welche Komponente grad geklickt wurde. das sieht dann so aus:

Java:
@Override
public void actionPerformed(ActionEvent e){
    if (e.getSource() == /*Hier muss dein Button von der Unterklasse stehen*/){
        machWasDerButtonMachsenSoll();
    }
    else if(e.getSource() == /*irgendeine andere Komponente*/){
    ...
    ...
}

Wie dir sicher auffällt, haben wir aber keinen Zugriff auf den Button, da er (sehr warsch.) eine private Eigenschaft von der Unterklasse ist. Entweder machst du in dieser Unterkomponete die Eigenschaft public und nennt sie direkt in der "Action-Methode" oder du machst halt das ganze mit einem getter(was "sauberer" wäre):

Java:
public class Oberklasse implements ActionListener{
    UntereKlasse uk;
    ...
    public void actionPerformed(ActionEvent e){
        if (e.getSource() == uk.mButton){           // Hier wird direkt auf den Button zugegriffen
            machWasDerButtonMachsenSoll();
        }
        ...
    }
    ...
}

public class UntereKlasse {
 
    private final ActionListener mActionListener;
    public JButton mButton;               // private -> public
    ...

oder halt:

Java:
public class Oberklasse implements ActionListener{
    UntereKlasse uk;
    ...
    public void actionPerformed(ActionEvent e){
        if (e.getSource() == uk.getButton()){           // Hier wird über einen Getter auf den Button zugegriffen
            machWasDerButtonMachsenSoll();
        }
        ...
    }
    ...
}

public class UntereKlasse {
 
    private final ActionListener mActionListener;
    private JButton mButton;
    ...

    public JButton getButton(){
        return mButton;
    }

    ...
}

So, hab jetzt mal fast alles ausführlich erklärt (Man könnte aber noch...blablabla) :lol:

Gruß, Thomas
 
Hi,
meinst du so was:
Java:
import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Test 
extends JFrame 
implements ActionListener {

    private final JButton button;
    private final JTextArea teaxtArea;

    private Test() {

        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        button = new JButton("Bitte drücken ...");
        button.addActionListener(this);

        teaxtArea = new JTextArea(5, 20);

        setLayout(new BorderLayout());
        add(teaxtArea, BorderLayout.CENTER );
        add(button, BorderLayout.SOUTH );

        pack();
        setVisible(true);

    }

    @Override
    public void actionPerformed(ActionEvent evt) {
        if (evt.getSource() == button) {
            teaxtArea.setText("Danke!");
        }
    }

    public static void main(String[] args) {
        new Test();
    }

}
?
Pepe
 
Nun du kannst am einfach bei der Erstellung der Buttons einfach .setName("oeffneDasMenueX"); verwenden um den Namen des Buttons zu setzen.

Dann kannst du in der ActionPerformed einfach dir den Button holen und dann getName() ausführen und schauen, welcher Name es ist.

Dabei entweder den Namen durch if/ else if "jagen" oder in einen switch(String s) packen (ab Java 7)
 
Aber geht das nicht auch schöner ?
Java:
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

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

public class Demo {
	public Demo() {
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setBounds(0, 0, 400, 200);
		frame.setLocationRelativeTo(null);
		frame.setLayout(new GridLayout(2, 1));
		Controller controller = new Controller() {
			public void machDas() {
				System.out.println("mach das");
			}

			public void machDies() {
				System.out.println("mach dies");
			}

			public void machSonstEtwas() {
				System.out.println("mach sonst etwas");
			}
		};
		frame.add(new Panel1(controller));
		frame.add(new Panel2(controller));
		frame.setVisible(true);
	}
	
	interface Controller {
		public void machDies();
		public void machDas();
		public void machSonstEtwas();
	}
	
	class Panel1 extends JPanel {
		private Controller control;
		
		public Panel1(Controller controller) {
			this.control = controller;
			this.setLayout(new GridLayout(1, 1));
			JButton button = new JButton("Dies");
			this.add(button);
			button.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					control.machDies();
				}
			});
		}
	}
	
	class Panel2 extends JPanel {
		private Controller control;
		
		public Panel2(Controller controller) {
			this.control = controller;
			this.setLayout(new GridLayout(1, 2));
			JButton button = new JButton("Das");
			this.add(button);
			button.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					control.machDas();
				}
			});
			button = new JButton("SonstEtwas");
			this.add(button);
			button.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent evt) {
					control.machSonstEtwas();
				}
			});
		}
	}
	
	public static void main(String[] s) {
		new Demo();
	}
}
 
"
Java:
button.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent evt) {
                    control.machDies();
                }
            });
"

Das wollte ich auch gerade vorschlagen. entweder du machst so eine "temporäre" direkt definierte Klasse oder du machst noch eine eigene weiter darunter, die alles abhandelt ("addActionListener(new MyCustomActionListener());"
 

Zurück
Oben