Observer|update()|methodenaufruf unvollständig

shxfreestyle

Grünschnabel
Hallo Leute,

Ich habe 2 Klassen, die eine ist ein Observable und die andere der Observer. Bei einem Buttonklick in der Observable-Klasse wird die Observer-Klasse benachrichtigt und dort die update()-methode aufgerufen, soweit so gut. In dieser update()-Methode soll die Hintergrundfarbe eines weiteren Buttons durch den Aufruf der Methode colorchange() geändert werden. Und genau hier hakt es. Die colorchange()-Methode wird zwar aufgerufen, aber die Hintergrundfarbe nicht geändert. Wenn ich die colorchange()-Methode jedoch durch einen Klick auf den Button dessen farbe geändert werden soll selbst aufrufe gibt es keine Probleme.
Weiß da jemand warum colorchange()-Methode durch den aufruf aus der update()-Methode nicht korrekt funktioniert?

hier die 2 Klassen:

Observable-Klasse: (evtl. UNWICHTIG)
Java:
public class observerable{

	static JFrame fenster = new JFrame("observerable");
	static JPanel inhalt = new JPanel();
	static JButton btnmain = new JButton("buttonmain");
	public static Observable o = new Observable();

	private static class MyObservable extends Observable {
	        @Override
	        public void setChanged() {
	            super.setChanged();
	        }
	    }
	private final static MyObservable observable = new MyObservable();

	public static void main(String[] args) {
	btnmain.addActionListener(new ActionListener(){
		public void actionPerformed(ActionEvent e) {
			observable.addObserver(new observer());
			observable.setChanged();
			observable.notifyObservers("test");
		}
	});		
	inhalt.add(btnmain);
	inhalt.add(new observer().btn());	
	fenster.setLocationRelativeTo(null);
	fenster.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	fenster.setVisible(true);
	fenster.add(inhalt);
	fenster.pack();
	}
}

Observer-Klasse: (WICHTIG)
Java:
public class observer  implements Observer{

	JButton btn = new JButton("test_button");
	
	public JButton btn(){
		btn.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent arg0) {
				colorchange(); // funktioniert
			}
		});
		return btn;
	}
	
	public void colorchange(){
		System.out.println("colorchange aufgerufen"); // wird in beiden fällen ausgegeben
		btn.setBackground(Color.RED); // funktioniert NUR durch aufruf weiter oben
	}
	
	@Override
	public void update(Observable o, Object arg) {
		System.out.println("test empfangen");
		colorchange(); // funktioniert NICHT
	}
}
 

Akeshihiro

Erfahrenes Mitglied
Hi und willkommen bei uns ^^

So vorweg: Die Klassen beginnen in Java mit einem Großbuchstaben.

Warum das Verhalten so ist, wie es ist, ist eigentlich schnell erklärt: Es gibt zwei Instanzen deines Observers. Die erste Instanz dient tatsächlich als Observer, die zweite Instanz dient nur dazu einen Button zu holen ...

Das betrifft die folgende Zeilengruppe:
Java:
private final static MyObservable observable = new MyObservable();
 
    public static void main(String[] args) {
    btnmain.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            observable.addObserver(new observer()); // <-- eine Instanz
            observable.setChanged();
            observable.notifyObservers("test");
        }
    });     
    inhalt.add(btnmain);
    inhalt.add(new observer().btn()); // <-- eine andere Instanz!!

Damit das funktioniert, müsste das so aussehen:
Java:
private final static MyObservable observable = new MyObservable();
 
    public static void main(String[] args) {
observer obs = new observer();
    btnmain.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent e) {
            observable.addObserver(obs);
            observable.setChanged();
            observable.notifyObservers("test");
        }
    });     
    inhalt.add(btnmain);
    inhalt.add(obs.btn());

Die gesamte Konstruktion ist aber doch ziemlich merkwürdig oder ums anders zu sagen, es ist alles irgendwie zusammengepfuscht. Ich habe mir mal erlaubt das Ganze zu überarbeiten und viel Sinn ergibt das alles noch immer nicht wirklich, aber es ist deutlich sauberer (der Button aus Observer ist aber da geblieben, ich weiß ja nicht, was du vor hast).

MyObservable.java
Java:
package de.tutorials.forum.help.shxfreestyle.observer;

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

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

public class MyObserverable extends Observable {
	private JFrame	frame;
	private JPanel	panel;
	private JButton	btnMain;

	public MyObserverable() {
		MyObserver myObserver = new MyObserver();
		addObserver(myObserver);

		frame = new JFrame("Observable");
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

		btnMain = new JButton("Main");
		btnMain.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				setChanged();
				notifyObservers("test");
			}
		});
		panel = new JPanel();
		panel.add(btnMain);
		panel.add(myObserver.getBtnTest());

		frame.add(panel);

		frame.pack();
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
	}

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

MyObserver.java
Java:
package de.tutorials.forum.help.shxfreestyle.observer;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;

import javax.swing.JButton;

public class MyObserver implements Observer {
	private JButton	btnTest;

	private void changeColor() {
		System.out.println("changeColor wurde aufgerufen!");

		Random random = new Random();
		int r = random.nextInt(256);
		int g = random.nextInt(256);
		int b = random.nextInt(256);
		getBtnTest().setBackground(new Color(r, g, b));
	}

	public JButton getBtnTest() {
		if(btnTest == null) {
			btnTest = new JButton("Test");
			btnTest.addActionListener(new ActionListener() {
				@Override
				public void actionPerformed(ActionEvent e) {
					changeColor();
				}
			});
		}

		return btnTest;
	}

	@Override
	public void update(Observable o, Object arg) {
		System.out.println("Parameter des Observable: " + arg);
		changeColor();
	}
}
 
Zuletzt bearbeitet:

shxfreestyle

Grünschnabel
vielen Dank für die schnelle Hilfe, funktionert super!
Ich bin dabei mir meine erste Anwendung zusammen zu pfuschen :D und da der Quellcode da ziemlich lang und unübersichtlich ist hab ich mein Problem auf ein Button übertragen der die Farbe wechselt. Bei dieser Anwendung lese ich Zeilen aus einer art Zip-Datei aus und diese werden dann in der GUI dargestellt und verändert. Und das aufrufen der Methode dient mir dazu nach dem Import einer neuen Datei, Teile des GUI zu aktualisieren. Naja, learning by doing xD

mfg shx