AWT Eventhandling

MisterB

Mitglied
Hallo zusammen,

studienbedingt muss ich mich derzeit mit AWT und Eventhandling beschäftigen. Da ich allerdings urspünglich aus der Visual Studio Welt komme, bin ich was das erstellen von GUIs betrifft dementsprechend verwöhnt.
Ich bin mittlerweile dahinter gekommen das Java einem unterschiedliche Konzepte zum Abfangen von Events zur Verfügung stellt, Schnittstelle implementieren, Vererben und Anonyme Klassen. Vom derzeitgen Wissensstand aus halte ich den Weg über Anonymeklasse momentan für den flexibleren und daher auch besseren Weg.

Ich habe also ein Frame und bin gerade dabei eine seperate Klasse für die Menüleiste mit Leben zufüllen. Dort stehen dann so Dinge drin wie (Das ist natürlich nur ein kleiner Auszug aus dem Quellcode um das Problem darstellen zu können).

Java:
public mubMain() {
    Menu mnuSpiel = new Menu("Spiel");
    MenuItem mitNeu = new MenuItem("Neues Spiel");
    mnuSpiel.add(mitNeu);
    this.add(mnuSpiel);
    mitNeu.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent AE) {
            System.out.println(AE.getActionCommand());
        }
    });
}

Ich erstelle also alles an Elementen was benötigt wird und hänge einen ActionListener ran. Die so angefertigte Klasse instanziere ich dann in einem Frame-Object in welchem sich auch die Main befindet und hänge es ein.

Was ich mich jetzt frage ist, wie komme ich von hier aus an andere Steuerelemente auf dem Frame. Zum Beispiel Beschriftungen eine Labels ändern etc.???:L

Wäre wirklich sehr nett wenn mir jemand helfen könnte. Danke im voraus. :)
 
G

Gast2

Gast
Ich erstelle also alles an Elementen was benötigt wird und hänge einen ActionListener ran. Die so angefertigte Klasse instanziere ich dann in einem Frame-Object in welchem sich auch die Main befindet und hänge es ein.

Was ich mich jetzt frage ist, wie komme ich von hier aus an andere Steuerelemente auf dem Frame. Zum Beispiel Beschriftungen eine Labels ändern etc.???:L

Du willst Beschriftungen ändern wenn du auf ein menü Knopf drückst?:bahnhof:

Normalerweise hat man einen Controller oder ein Command welches regelt was passiert wenn man xyz drückt.

Observer (Entwurfsmuster) ? Wikipedia
und
Model View Controller ? Wikipedia
 

Fu3L

Top Contributor
Mit mubMain.this.variablenName
(oder andersrum was die ersten beiden Teile angeht, da vertue ich mich oft^^)

Ich finde persönlich besser die Klasse, zu der die Komponenten hinzugefügt werden, zB ActionListener implementieren zu lassen und mit

JComponent.addActionListener(this);

die Klasse das EventHandling machen zu lassen, aber für einen einzelnen Button lohnt sich das natürlich nicht^^ Aber bei mehreren MenuItems kann sich das denke ich schon lohnen^^ Innerhalb der einen actionPerformed-Methode kann man ja mit ActionEvent.getActionCommand() abfragen, welches Item gedrückt wurde.
 

Fu3L

Top Contributor
Ich hoffe, die "allgemein akzeptierte" Variante ist nicht die, dass man nach jedem erzeugten Button etc. erstma ne Annonyme Klasse baut? Dass man bei größeren Softwares das nach MVC macht, ist klar, aber für ein kleines Menü für ein kleines Spielchen oder ähnliches wäre mir das zu viel drumrum^^
 
G

Gast2

Gast
Ich hoffe, die "allgemein akzeptierte" Variante ist nicht die, dass man nach jedem erzeugten Button etc. erstma ne Annonyme Klasse baut? Dass man bei größeren Softwares das nach MVC macht, ist klar, aber für ein kleines Menü für ein kleines Spielchen oder ähnliches wäre mir das zu viel drumrum^^

Versteh nicht was du meinst? Aber ja so macht man es...
Besser als 100 if Abfragen mit getActionCommand
 

Fu3L

Top Contributor
Mich störts beim Erstellen der GUI, wenn immer die ganzen Klassen im Weg stehen^^ Gibt ja auch Fälle, wo man zB nur den ActionCommand an ne Methode weitergeben muss.. Ist denke ich mal ne Geschmackssache^^
Vllt kann der TO ja aus den Argumenten lernen :)
 
G

Gast2

Gast
Mich störts beim Erstellen der GUI, wenn immer die ganzen Klassen im Weg stehen^^ Gibt ja auch Fälle, wo man zB nur den ActionCommand an ne Methode weitergeben muss.. Ist denke ich mal ne Geschmackssache^^
Vllt kann der TO ja aus den Argumenten lernen :)

Mach mal ein Beispiel ich verstehe deine Argumente nicht.
 

Fu3L

Top Contributor
Selbstverständlich ein sehr stumpfes Beispiel^^ Aber das gehört zu meinem Argument, dass man vllt nur den Text des Buttons oder dessen ActionCommand übermitteln muss an eine Methode^^

Java:
public class Action extends JFrame implements ActionListener {
	
	JLabel lbl;
	
	Action() {
		this.setSize(400, 400);
		this.setLayout(new FlowLayout());
		this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);
		
		JButton btn = new JButton("Hallo");
		btn.addActionListener(this);
		this.add(btn);
		
		btn = new JButton("Welt");
		btn.addActionListener(this);
		this.add(btn);
		
		btn = new JButton("!");
		btn.addActionListener(this);
		this.add(btn);
		
		lbl = new JLabel();
		this.add(lbl);
		
		this.setVisible(true);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		lbl.setText(e.getActionCommand());
		validate();
		repaint();
	}

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

Gast2

Gast
Warum sollte man sowas tun?^^ Nicht gerade sinvoll ;). Listener stellen auch GUI-Controller dar!!!

Wie gesagt meistens folgt auf einen Button Druck ein Controller/Comman aufruf.
 

Fu3L

Top Contributor
Naja, natürlich bietet sichs bei sowas schon an, das nach MVC zu lösen, aber sagen wir, du willst eine Liste mit Daten darstellen (jeder Datensatz hat seine eigene ID) und am Ende jeder Zeile steht ein Button mit nem x zum Löschen (und der ID als ActionCommand) und du willst dann die ID haben und die deiner Methode zum Löschen eines Datensatzes mitgeben^^ Da könnte man das so lösen wie bei dem Label-Text im Beispiel oben^^

Edit: Zeig mir bitte mal ein Beispiel, damit ich wirklich deine Skepsis nachvollziehen kann, dann hätte ich auch nachhaltig was gelernt in diesem Thread ;)
 

MisterB

Mitglied
Zunächst einmal vielen herzlichen Dank für die vielen schnellen Antworten.:)

Du willst Beschriftungen ändern wenn du auf ein menü Knopf drückst?:bahnhof:

Na ja, eigentlich nicht, das Beispiel sollte nur meine Fragestellung etwas illustrieren. Wenn ich allzu sehr auf das Problem eingehe und hier fertigen Code erhalten sollte, mosern die Tutoren wieder. Also habe ich etwas vom eigentlichen Problem abstrahiert damit ich mir wenigstens etwas Transferleistung zuschreiben darf. :)

Ich habe es mir jetzt einfach gemacht und alle GUI-Elemente in eine Klasse geschmissen, welche von Frame erbt. Sieht nach meinem dafürhalten zwar nicht allzu schön aus, erfüllt aber seinen Zweck.
 
G

Gast2

Gast
Edit: Zeig mir bitte mal ein Beispiel, damit ich wirklich deine Skepsis nachvollziehen kann, dann hätte ich auch nachhaltig was gelernt in diesem Thread ;)

hier mal ein beispiel meinerseits sourcen liegen bei:

Der Teil der dich wahrscheinlich am meisten interessiert ist hier:
Ich mach das so :
Java:
public class InfoView extends JPanel{

	private JTextField  field;
	public InfoView(final KundenController controller){
		super();
		setBorder(BorderFactory.createTitledBorder("Kunde anlegen"));
		field = new JTextField();
		field.setPreferredSize(new Dimension(100,25));
		add(field);
		add(new JButton(new AbstractAction("Anlegen") {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				controller.addKunde(createKunde());
				field.setText("");
			}
		}));
		
		add(new JButton(new AbstractAction("Löschen") {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				controller.removeKunde(createKunde());
			}
		}));
	}
	
	private Kunde createKunde(){
		//Hier ne Factory oder Sosntiges benutzen
		Kunde k = new KundenImpl();
		k.setName(field.getText());
		return k;
	}
}


Anstatt

Java:
public class InfoView extends JPanel implements ActionListener{

	private JTextField  field;
	private KundenController controller;
	public InfoView(final KundenController controller){
		super();
		this.controller = controller;
		setBorder(BorderFactory.createTitledBorder("Kunde anlegen"));
		field = new JTextField();
		field.setPreferredSize(new Dimension(100,25));
		add(field);
		
		JButton buttonAnlegen = new JButton("Anlegen");
		buttonAnlegen.addActionListener(this);
		
		add(buttonAnlegen);
		
		JButton buttonRemove = new JButton("Löschen");
		buttonRemove.addActionListener(this);
		
		add(buttonRemove);
	}
	
	private Kunde createKunde(){
		//Hier ne Factory oder Sosntiges benutzen
		Kunde k = new KundenImpl();
		k.setName(field.getText());
		return k;
	}

	@Override
	public void actionPerformed(ActionEvent ae) {
		if(ae.getActionCommand().equals("Anlegen")){
			controller.addKunde(createKunde());
			field.setText("");
		}else if(ae.getActionCommand().equals("Löschen")){
			controller.removeKunde(createKunde());
		}
		
	}
}

1. die ifs sind häßlich vor allem wenn man bedenkt es kommen noch mehr Elemente hinzu
2. wenn sich die Beschriftung des Buttons ändert musst du den rest auch nachziehen (Mehr Aufwand)
3. Außerdem kann jetzt von außen jeder die InfoView als ActionListener adden obwohl die InfoView KEINE Action darstellt.
 

Anhänge

  • mvc.jar
    13 KB · Aufrufe: 5

Fu3L

Top Contributor
wenn sich die Beschriftung des Buttons ändert musst du den rest auch nachziehen (Mehr Aufwand)

Das ist für mich am überzeugensten^^ Selbst wenn mans mit setActionCommand macht, hab ich schonma gemerkt, dass es ätzend sein kann (insbesondere, weil der Compiler einen hier nicht auf Tippfehler hinweist ;))^^ Und beim Hinzufügen neuer Buttons etc. muss man immer durch die Gegend scrollen^^
 
G

Gast2

Gast
Das ist für mich am überzeugensten^^ Selbst wenn mans mit setActionCommand macht, hab ich schonma gemerkt, dass es ätzend sein kann (insbesondere, weil der Compiler einen hier nicht auf Tippfehler hinweist ;))^^ Und beim Hinzufügen neuer Buttons etc. muss man immer durch die Gegend scrollen^^

Du musst auch so sehen, dass ein ActionListener ein Controller darstellt und deine widgets z.B. JPanel sind eben keine Controller. Deshalb eher eine innere Klasse machen oder aber was ich am besten sind sind die anonymen Klassen übersichtlich und kurz.
 

Ähnliche Java Themen


Oben