简体   繁体   中英

Java: SwingPropertyChangeSupport

I am trying to make an MVC Java Swing program that makes use of SwingPropertyChangeSupport to notify the view whenever the model gets updated. The problem I am having is that the notifications do not seem to be happening.

I have prepared an SSCCE below. In the SSCCE, there is a Swing GUI that has a button and a text field. When you click the button, a counter in the model gets incremented, and the view is supposed to get notified so that it can update itself. However, it appears the notifications do not get sent/received (I am not sure which -- it could be both) even though I have checked to make sure that oldValue and newValue are different from each other. I would appreciate any assistance in understanding where I've gone wrong. Thanks!

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.SwingPropertyChangeSupport;


public class Main extends JFrame {

    public Main() {
        PropertyChangeView theGui = new PropertyChangeView();
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setResizable(true);
        add(theGui);
        pack();
        setVisible(true);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new Main();
            }
        });
    }
}


class PropertyChangeView extends JPanel {
    private JButton button;
    private JTextField textfield;
    private GridBagConstraints gbc;
    private PropertyChangeController controller;

    public PropertyChangeView() {
        super(new GridBagLayout());
        controller = new PropertyChangeController();
        button = new JButton("Click me to increment the count");
        textfield = new JTextField(10);

        button.addActionListener(new ButtonListener());
        addPropertyChangeListener(new MyPropertyChangeListener());

        gbc = new GridBagConstraints();
        gbc.gridheight = 1;
        gbc.gridwidth = 1;
        gbc.anchor = GridBagConstraints.LINE_START;
        gbc.fill = GridBagConstraints.BOTH;

        gbc.gridx = 0;
        gbc.gridy = 0;
        add(button, gbc);

        gbc.gridx = 1;
        gbc.gridy = 0;
        add(textfield, gbc);
    }

    private class MyPropertyChangeListener implements PropertyChangeListener {
        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            System.out.println("Event received " + evt);

            if (evt.getPropertyName().equals(PropertyChangeModel.CHANGED)) {
                textfield.setText(evt.getNewValue().toString());
            }
        }
    }

    private class ButtonListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e) {
            controller.setCounter(controller.getCounter() + 1);
            System.out.println("counter now = " + controller.getCounter());
        }
    }

}


class PropertyChangeController {
    private PropertyChangeModel model;

    public PropertyChangeController() {
        model = new PropertyChangeModel();
    }

    public int getCounter() {
        return model.getCounter();
    }

    public void setCounter(int i) {
        model.setCounter(i);
    }
}


class PropertyChangeModel {
    public static final String CHANGED = "property change model updated";

    private int counter;
    private SwingPropertyChangeSupport pcs;

    public PropertyChangeModel() {
        counter = 0;
        pcs = new SwingPropertyChangeSupport(this);
    }

    public int getCounter() {
        return counter;
    }

    public void setCounter(int i) {
        int oldValue = counter;
        int newValue = i;
        counter = newValue;
        pcs.firePropertyChange(CHANGED, oldValue, newValue);
        System.out.println("setCounter finished with oldValue=" + oldValue + ", newValue=" + newValue);
    }
}

I've not run your program, but I see one thing out of order here:

public void setCounter(int i) {
    int oldValue = counter;
    int newValue = i;
    pcs.firePropertyChange(CHANGED, oldValue, newValue);
    counter = newValue;
    System.out.println("setCounter finished with oldValue=" + oldValue + ", newValue=" + newValue);
}

which should be:

public void setCounter(int i) {
    int oldValue = counter;
    int newValue = i;
    counter = newValue;
    pcs.firePropertyChange(CHANGED, oldValue, newValue);
    System.out.println("setCounter finished with oldValue=" + oldValue + ", newValue=" + newValue);
}

You should fire notification only after updating the model's value.

Your main problem though is that you add no PropertyChangeListener to the model.


eg

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;
import javax.swing.event.SwingPropertyChangeSupport;

public class Main extends JFrame {

   public Main() {
      PropertyChangeView theGui = new PropertyChangeView();
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      setResizable(true);
      add(theGui);
      pack();
      setVisible(true);
   }

   public static void main(String[] args) {
      SwingUtilities.invokeLater(new Runnable() {
         public void run() {
            new Main();
         }
      });
   }
}

class PropertyChangeView extends JPanel {
   private JButton button;
   private JTextField textfield;
   private GridBagConstraints gbc;
   private PropertyChangeController controller;

   public PropertyChangeView() {
      super(new GridBagLayout());
      PropertyChangeModel model = new PropertyChangeModel();
      controller = new PropertyChangeController(model);
      button = new JButton("Click me to increment the count");
      textfield = new JTextField(10);

      button.addActionListener(new ButtonListener());
      model.addPropertyChangeListener(new MyPropertyChangeListener());


      gbc = new GridBagConstraints();
      gbc.gridheight = 1;
      gbc.gridwidth = 1;
      gbc.anchor = GridBagConstraints.LINE_START;
      gbc.fill = GridBagConstraints.BOTH;

      gbc.gridx = 0;
      gbc.gridy = 0;
      add(button, gbc);

      gbc.gridx = 1;
      gbc.gridy = 0;
      add(textfield, gbc);
   }

   private class MyPropertyChangeListener implements PropertyChangeListener {
      @Override
      public void propertyChange(PropertyChangeEvent evt) {
         System.out.println("Event received " + evt);

         if (evt.getPropertyName().equals(PropertyChangeModel.CHANGED)) {
            textfield.setText(evt.getNewValue().toString());
         }
      }
   }

   private class ButtonListener implements ActionListener {
      @Override
      public void actionPerformed(ActionEvent e) {
         controller.setCounter(controller.getCounter() + 1);
         System.out.println("counter now = " + controller.getCounter());
      }
   }

}

class PropertyChangeController {
   private PropertyChangeModel model;

   // public PropertyChangeController() {
   // model = new PropertyChangeModel();
   // }


   public PropertyChangeController(PropertyChangeModel model) {
      this.model = model;
   }

   public int getCounter() {
      return model.getCounter();
   }


   public void setCounter(int i) {
      model.setCounter(i);
   }
}

class PropertyChangeModel {
   public static final String CHANGED = "property change model updated";

   private int counter;
   private SwingPropertyChangeSupport pcs;

   public PropertyChangeModel() {
      counter = 0;
      pcs = new SwingPropertyChangeSupport(this);
   }

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

   public int getCounter() {
      return counter;
   }

   public void setCounter(int i) {
      int oldValue = counter;
      int newValue = i;
      counter = newValue;
      pcs.firePropertyChange(CHANGED, oldValue, newValue);
      System.out.println("setCounter finished with oldValue=" + oldValue
            + ", newValue=" + newValue);
   }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM