using ChangeListener to fire changes in Java Swing?

brain storm picture brain storm · Nov 22, 2013 · Viewed 8.6k times · Source

I am implementing a word guessing game. The attached image gives an idea of what I am doing. My GamePane consists of two components, ControlPane and HangManPane, which is the top and bottom section of the attached image. when the player clicks, New Game button, the GamePane must be notified. subsequently, the GamePane will request the SecretWord from ControlPane and pass it on to HangManPane to construct the model.

so two things happen here which I would like to know how to implement

  1. ControlPane should fire notifications when the user clicks "New Game" button.so this fireChange should happen in the ActionListener of the New Game button.

  2. GamePane listens to the notifications and pass the information to HangManPane

Using ChangeListener would be appropriate. I did my part of searching, but unable to grasp on how to implement here. Any suggestions are kindly welcome

public class GamePane extends JPanel {

    public GamePane(){
         ControlPane cp = new ControlPane();
         //if user clicks New Game on ControlPane, notify me
         //I will then do the following 
         HangManModel model = new DefaultHangManModel(cp.getSecretWord());
         HangManPane hangManPane = new HangManPane(model);

         setLayout(new GridLayout(0,1));
         this.add(cp);
         this.add(pane);

    }
 }

enter image description here

Answer

MadProgrammer picture MadProgrammer · Nov 23, 2013

Providing listener support is "relatively" simple. It's simplified by the fact the JComponent exposes it's EventListenerList (listenerList) as a protected variable.

In the ControlPane, you'll need an add method...

public void addChangeListener(ChangeListener listener) {
    listenerList.add(ChangeListener.class, listener);
}

You'll need a remove method

public void removeChangeListener(ChangeListener listener) {
    listenerList.remove(ChangeListener.class, listener);
}

Now, you need some way to actually raise or fire events as needed...

protected void fireStateChanged() {
    ChangeListener[] listeners = listenerList.getListeners(ChangeListener.class);
    if (listeners != null && listeners.length > 0) {
        ChangeEvent evt = new ChangeEvent(evt);
        for (ChangeListener listener : listeners) {
            listener.stateChanged(evt);
        }
    }
}

Now, when ever you want to tell registered listeners that the ControlPane state has changed, you would simply call fireStateChanged, for example...

public void actionPerformed(ActionEvent evt) {
    fireStateChanged();
}

Now, in the GamePane, you will need to register a ChangeListener against the instance of the ControlPane...

private ControlPane cp;
private HangManPane hangManPane;

//...

public GamePane() {
    cp = new ControlPane();
    hangManPane = new HangManPane(null);

    cp.addChangeListener(new ChangeListener() {
        public void stateChanged(ChangeEvent evt) {
            String secret = cp.getSecretWord();
            DefaultHangManModel model = new DefaultHangManModel(secret);
            hangManPane.setModel(model);
        }
    });
}

For example...