2

我正在尝试制作一个 MVC Java Swing 程序,该程序利用 SwingPropertyChangeSupport 在模型更新时通知视图。我遇到的问题是通知似乎没有发生。

我在下面准备了一个 SSCCE。在 SSCCE 中,有一个带有按钮和文本字段的 Swing GUI。当您单击按钮时,模型中的计数器会增加,并且视图应该会收到通知,以便它可以自行更新。但是,即使我已经检查以确保 oldValue 和 newValue 彼此不同,但似乎没有发送/接收通知(我不确定哪个 - 它可能是两者)。我将不胜感激任何帮助了解我哪里出错了。谢谢!

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);
    }
}
4

1 回答 1

3

我没有运行你的程序,但我在这里看到一件事有问题:

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);
}

应该是:

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);
}

您应该仅在更新模型的值后触发通知。

不过,您的主要问题是您没有向模型添加 PropertyChangeListener。


例如

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);
   }
}
于 2015-06-02T22:22:22.750 回答