0

My problem is that when I change the value from a property of my model the PropertyChangeSupport fires but the PropertyChangeListener in the view is never reached. So I guess I am making something wrong by adding the listener.

Any kind of input is appreciated.

package stackOverflow.allInOne;

import java.awt.FlowLayout;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import static java.lang.System.getProperty;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.WindowConstants;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;


public class AllInOne {
        public static void main(String[] args) {
        final Model Model = new Model();
        final Controller Controller = new Controller(Model);
        Controller.initializeView();
    }
}

class View extends JFrame{

        private final Model model;
    private final Controller controller;

        JTextField fldAny;
    JButton btnAny; 

    public View(Model model, Controller controller) {
        super("SBB app");
        this.model = model;
        this.controller = controller;
    }

    public void createAndShow() {
        initializeComponents();
        JPanel contents = layoutComponents();
        addActionEvents();
        addPropertyChangeListeners();  

        add(contents);
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        pack();
        setVisible(true);
        }

    private void initializeComponents() {
        fldAny = new JTextField("----------");
        btnAny = new JButton("klick me");
    }

    private JPanel layoutComponents() {
        JPanel anyPanel = new JPanel(new FlowLayout());
        anyPanel.add(fldAny);
        anyPanel.add(btnAny);
        return anyPanel;
    }

    private void addActionEvents() {
        fldAny.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void changedUpdate(DocumentEvent e) {
                change();
            }
            @Override
            public void insertUpdate(DocumentEvent e) {
                change();
            }
            @Override
            public void removeUpdate(DocumentEvent e) {
                change();
            }
            public void change() {
                                 System.out.println("action event fired");
                                 controller.setNewValue(fldAny.getText());
             }
        });
    }

    private void addPropertyChangeListeners() {
        PropertyChangeListener myListener = new MyPropertyChangeListener(this);
                List<Model2> xx = model.getAllModel2();
                for(Model2 x : xx){
                    x.addPropertyChangeListener(Model2.BTN_TXT, myListener);
                }
    }
}

class MyPropertyChangeListener implements PropertyChangeListener{
    private View view;

    public MyPropertyChangeListener(View view) {
        this.view = view;
    }

         @Override
         public void propertyChange(PropertyChangeEvent evt) {
                 System.out.println(evt);
                 System.out.println("Receved the fire");
                 view.btnAny.setText(view.btnAny.getText() + "1");
         }
}

 class Model2{
    private String fldText;
    private String btnText;

    public static final String BTN_TXT = "btnText";
    private final PropertyChangeSupport pcs = new PropertyChangeSupport(this);

    Model2(String fldText, String btnText) {
        this.fldText = fldText;
        this.btnText = btnText;
    } 

    public void setFldText(String fldText) {
        this.fldText = fldText;
    }

    public String getFldText() {
        return fldText;
    }

    public String getBtnText() {
        return btnText;
    }

    public void setBtnText(String btnText) {
        System.err.println("Model fires");
        pcs.firePropertyChange(BTN_TXT, btnText, this.btnText = btnText);
    }

    public void addPropertyChangeListener(PropertyChangeListener listener) {
        pcs.addPropertyChangeListener(listener);
    }

    public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        System.out.println("Listener wird zu " +listener.toString() + " hinzugefügt mit property " +  propertyName);
                pcs.addPropertyChangeListener(propertyName, listener);
        final Object value = getProperty(propertyName);
        listener.propertyChange(new PropertyChangeEvent(this, propertyName,
                value, value));
    }

    public void removePropertyChangeListener(PropertyChangeListener listener) {
        pcs.removePropertyChangeListener(listener);
    }

    public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
        pcs.removePropertyChangeListener(propertyName, listener);
    }

    public PropertyChangeListener[] getPropertyChangeListeners() {
        return pcs.getPropertyChangeListeners();
    }

    public PropertyChangeListener[] getPropertyChangeListeners(String propertyName) {
        return pcs.getPropertyChangeListeners(propertyName);
    }

}

 class Model {
    private List<Model2> model2List = new ArrayList<Model2>();


    public Model() {
        model2List.add(new Model2("fldText","btnText"));
    }

    public Model2 getSelectdModel2(){
        return model2List.get(0);
    }

    List<Model2> getAllModel2() {
        return model2List;
    }
}

 class Controller {
        private final Model model;

        public Controller(Model model) {
        this.model = model;

    }

    public void initializeView() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                View view = new View(model, Controller.this);
                view.createAndShow();
            }
        });
    }

    void setNewValue(String text) {
        System.out.println("Controller sets new value");
        model.getSelectdModel2().setBtnText(text);
    }

}

I am currently getting the following output when I start the Application:

Listener wird zu stackOverflow.allInOne.MyPropertyChangeListener@cee47f1 hinzugefügt mit property btnText java.beans.PropertyChangeEvent[propertyName=btnText; oldValue=null; newValue=null; propagationId=null; source=stackOverflow.allInOne.Model2@6fb525d8] Receved the fire

So I am a little bit confused why I am getting this fire because I am setting the value of the btnTxt before I am adding the listener to it. Anyway if I change the text in the field then I am getting the following output:

action event fired Controller sets new value Model fires

So as mentioned in my initial question it seems to my that

x.addPropertyChangeListener(Model2.BTN_TXT, myListener);

Doesn't always work.

  • 3
    1. PropertyChangeListener/Support is here very good, in some case excelent described, search for .... by click to PropertyChangeListener tag, 2. then to return with question based on SSCCE, short, runnable, compilable, everything described in your question is about 30-50 code lines inc. main class 3. this question isn't answerable without important details (read Oracle tutorial about) that I missing in your question – mKorbel Dec 15 '13 at 12:08
  • Thank you mKorbel for the tipps I searched like a madman but maybe I am to overtired or to dump to find my problem on my own. So wrote a code example about my problem. I hope this helps. – user3104185 Dec 15 '13 at 14:40
  • not an SSCCE, no idea where is your issue, in your models or, wrong notifiers between controler and view or ... ???, – mKorbel Dec 15 '13 at 17:43
  • I hope I made the code now SSCCE standard. It is a little bit long but I guess it has to when it needs to be executable. Well about the issue I don't know the aktual problem because of the output I can only guess that the changelistener is added because of the line 'Listener wird zu stackOverflow.allInOne.MyPropertyChangeListener@cee47f1 hinzugefügt mit property btnText' but on the otherside it doesn't react to the fire in the set of the model which is executed because of the output: 'Model fires'. Sorry for the trouble. – user3104185 Dec 15 '13 at 21:37
  • [please to look here](http://stackoverflow.com/questions/8169964/is-mvc-in-swing-thread-safe), I'm hope that isn't so far (there is multiplyed PropertyXxxXxx) – mKorbel Dec 15 '13 at 21:39

1 Answers1

0

And the error was so simple. The Fire and the listener worked. The only problem was that the propertychangesupport never really fired because I was passing every time the same value:

pcs.firePropertyChange(BTN_TXT, btnText, this.btnText = btnText);

While the secound parameter is supposed to be the old value and the third the new one. Because I was already assigning my old variable with the new value this.btnText = btnText the pcs thought the values where the same and didn't changed anything.

So the right example would be:

pcs.firePropertyChange(BTN_TXT, this.btnText, btnText); this.btnText = btnText;

Thanks for the help