Java:SwingPropertyChangeSupport

Java:SwingPropertyChangeSupport,java,swing,propertychangelistener,propertychangesupport,Java,Swing,Propertychangelistener,Propertychangesupport,我试图制作一个MVC Java Swing程序,它利用SwingPropertyChangeSupport在模型更新时通知视图。我遇到的问题是,通知似乎没有发生 我在下面准备了一份SSCCE。在SSCCE中,有一个Swing GUI,它有一个按钮和一个文本字段。当您单击该按钮时,模型中的计数器将递增,并且该视图应该得到通知,以便它可以更新自身。然而,尽管我已经检查了oldValue和newValue是否彼此不同,但似乎没有发送/接收到通知(我不确定是哪一个——可能两者都有)。如果有人能帮助我了解

我试图制作一个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);
    }
}

我没有运行您的程序,但我发现有一件事不正常:

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


e、 g


谢谢,我已经更新了代码示例,以便在触发通知之前放置
计数器=newValue
。至于PropertyChangeListener,我在视图中添加了一个,因为我希望得到通知。这不对吗?(我想这一定是因为我的程序不工作了!)@user1002119:这是倒过来的。您将侦听器添加到正在侦听的项中,以获取对模型的更改。然后,您的侦听器将通知视图。请查看上面对代码的更改。@user1002119:虽然我会在一个单独的类中创建单个控件/模型和视图,并将它们连接起来,但是为了回答的速度(我必须去工作),我还没有对您的代码做这么大的更改。感谢您花时间帮助我!那么您将侦听器添加到触发属性更改通知的同一个对象?您更新的示例确实很有帮助,我能够在我的实际项目中实现这一点。再次感谢!
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);
   }
}