Tom K
Tom K

Reputation: 319

Observer/Observable in a GUI

I asked a similar question a while back and I'm trying to implement the solution. I have a JPanel that will eventually have a number of controls on it to generate a number, but right now it just has a single JButton as a test. I am using Observer and Observable to have that JPanel let the JFrame know something has changed. I seem to be able to tell the Observer to watch for something, but the update() doesn't seem to call the Observer object. I am not sure where I am going wrong and finding a good tutorial on Observer/Observable is almost impossible.

The Object Subpanel extends Observable and inside Subpanel is the JPanel that I add to the JFrame. This seems to be the only way I can get a GUI to also extend Observable.

I'm sorry if this sounds confusing. I'm not sure how else to explain it. I just want an GUI menu object to be able to notify the JFrame when a change occurs.

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

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


public class TestObserver implements Observer{

    JFrame frame = new JFrame();

    //The panel in the frame that is to be watched for a change.
    SubPanel sf = new SubPanel();


    TestObserver(){

        frame.setTitle("New Program!");
        frame.setSize(300, 200);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new FlowLayout());


        sf.addOutsideObserver(this);

        frame.add(sf.panel);
        frame.setVisible(true);
    }

    @Override
    public void update(Observable arg0, Object arg1) {
        // TODO Auto-generated method stub
        System.out.println("I have been notified!");
    }

    public static void main(String[] args) {
        TestObserver mf = new TestObserver();
    }
}

class SubPanel extends Observable implements ActionListener{
    JPanel panel = new JPanel();
    JButton b = new JButton();
    int count = 0;

//  Observer ob = new Observer();

    SubPanel(){
        b.addActionListener(this);
        panel.add(b);
    }

    @Override
    public void actionPerformed(ActionEvent arg0) {
        // TODO Auto-generated method stub
        // The counter is not important, just something to display
        count++;
        System.out.println("Count: " + count);
        // This does not seem to be happening in the Observer object
        notifyObservers();
    }

    public void addOutsideObserver(Observer o){
        addObserver(o);
        System.out.println("I'm added!");
    }
}

Upvotes: 0

Views: 2744

Answers (2)

PM 77-1
PM 77-1

Reputation: 13334

notifyObservers() acts only after a change occurs (as verified by hasChanged() method).

In your code you need to add setChanged() in order to set the change indicator before calling notify.

You do not need to call clearChanged() afterwards since this method is called automatically by the notifyObservers methods.

Upvotes: 3

regulus
regulus

Reputation: 1622

Observable class has a member called changed defaulted to false which can be modified by protected setChanged method. notifyObservers method just returns without doing anything if changed is false. So before you call notifyObservers call setChanged first, so it'll update the observers.

public void notifyObservers(Object arg) {
    if (!changed)
        return;
    ...
}

Edit: I've just noticed the answer was already provided in the comments.

Upvotes: 1

Related Questions