首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于SpinnerNumberModel的PropertyChangeSupport

用于SpinnerNumberModel的PropertyChangeSupport
EN

Stack Overflow用户
提问于 2011-08-07 07:45:31
回答 4查看 2.8K关注 0票数 7

我想要监听JSpinner的SpinnerNumberModel值的变化。

我创建了一个PropertyChangeSupport并将模型放入其中。

我需要propertyChangeListener,因为它显示了该属性的旧值和新值。

代码片段不起作用:当我单击JSpinner时,propertyChange方法不打印任何内容。

一个简单的ChangeListener只给出新的值,但我也需要旧的值,我怎么才能得到它?

代码语言:javascript
复制
package de.unikassel.jung;

import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import javax.swing.JFrame;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;

public class PropertyChangeTest implements PropertyChangeListener {

    public static void main(String[] args) {
        new PropertyChangeTest();
    }

    public PropertyChangeTest() {
        JFrame frame = new JFrame();
        frame.setBounds(100, 100, 450, 300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        int value = 1;
        int min = 0;
        int max = 10;
        int step = 1;
        SpinnerNumberModel spinnerModel = new SpinnerNumberModel(value, min, max, step);

        PropertyChangeSupport pcs = new PropertyChangeSupport(spinnerModel);
        pcs.addPropertyChangeListener("value", this);

        JSpinner spinner = new JSpinner(spinnerModel);
        frame.getContentPane().add(spinner);
        frame.setVisible(true);
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        System.out.println(evt);
        System.out.println(evt.getSource());
    }

}
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2011-08-07 09:53:49

不是听模型,而是听编辑器的JFormattedTextField,如下所示。

代码语言:javascript
复制
JSpinner spinner = new JSpinner(new SpinnerNumberModel(1, 0, 10, 1));
JSpinner.DefaultEditor editor = (JSpinner.DefaultEditor) spinner.getEditor();
editor.getTextField().addPropertyChangeListener("value", this);
票数 6
EN

Stack Overflow用户

发布于 2011-08-08 16:10:37

星期一早上..。不抗拒几条评论的经典时间:-)

@timaschew

  • “需要propertyChangeListener,因为它显示了属性的新旧值。”-(吹毛求疵--但总是强烈要求分离需求和解决方案:),我认为情况正好相反:在更改通知中,你需要访问旧值和新值,属性change /Listener是一个支持它的通知类型,可能不应该在观察代码的一部分使用属性。它应该用在可观察性的一侧(就像@Hovercraft在他的例子中所做的那样):它唯一的责任是管理和通知注册到observable
  • occasionally,的侦听器,accessibleContext为黑客提供了一个钩子-然而,它是一个钩子(除非你真的需要支持可访问性,情况很可能是这样:-)就像所有的黑客一样,这是一个脆弱的解决方案,很可能会在未来的某个时候带来痛苦。更稳定地跟踪有关操作和AbstractButton如何与

交互的链接

@Hovercraft

  • 使用更丰富的更改通知增强模型是可行的(如:我绝对最喜欢的:-)
  • 只有一个小细节:如果你有一个从属,让他来做所有的工作- PropertyChangeSupport有接受旧/新值的方法,不需要馈送来在可观察对象上创建事件。当新旧通知事件中的

newValue相等时,它将被丢弃,请不要使用该参数,而是再次使用getValue (超级用户可能已经拒绝了更改)

@垃圾神

哈哈-你已经猜到我不喜欢解决方案:它破坏了封装,因为它依赖于实现细节,所以除了完全控制JSpinner创建并且绝对确保其编辑器永远不会更改之外,不要这样做

票数 5
EN

Stack Overflow用户

发布于 2011-08-07 12:01:47

要让PropertyChangeSupport正常工作,您需要调用它的firePropertyChange方法,但更重要的是,support对象需要能够访问它正在侦听的属性的setXXX方法,并且在该方法中,它需要调用PropertyChangeSupport的firePropertyChange方法。因此,我认为要使您的想法生效,您需要扩展模型的类,为其提供一个PropertyChangeSupport对象,为其提供add和remove侦听器方法,并确保侦听模型的setValue方法中所做的更改。在我的示例中,该方法如下所示:

代码语言:javascript
复制
   @Override
   public void setValue(Object newValue) {
      // store old value and set the new one
      Object oldValue = getValue();
      super.setValue(newValue);

      // construct the event object using these saved values
      PropertyChangeEvent evt = new PropertyChangeEvent(this, VALUE, oldValue,
               newValue);

      // notify all of the listeners
      pcs.firePropertyChange(evt);
   }

下面是我使用PropertyChangeSupport的示例模型类:

代码语言:javascript
复制
import java.beans.*;
import javax.swing.*;
import javax.swing.event.*;

@SuppressWarnings("serial")
class MySpinnerNumberModel extends SpinnerNumberModel {
   public static final String VALUE = "value";
   private SwingPropertyChangeSupport pcs = new SwingPropertyChangeSupport(this);

   // you will likely need to create multiple constructors to match
   // the ones available to the SpinnerNumberModel class
   public MySpinnerNumberModel(int value, int min, int max, int step) {
      super(value, min, max, step);
   }

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

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

   @Override
   public void setValue(Object newValue) {
      // store old value and set the new one
      Object oldValue = getValue();
      super.setValue(newValue);

      // construct the event object using these saved values
      PropertyChangeEvent evt = new PropertyChangeEvent(this, VALUE, oldValue,
               newValue);

      // notify all of the listeners
      pcs.firePropertyChange(evt);
   }
}

最后测试类来测试上面的类,看看它是否正常工作:

代码语言:javascript
复制
import java.beans.*;
import javax.swing.*;

public class TestSpinnerPropChange {

   private static void createAndShowUI() {
      final MySpinnerNumberModel myModel = new MySpinnerNumberModel(1, 0, 10, 1);
      final JSpinner spinner = new JSpinner(myModel);

      final JTextField oldValueField = new JTextField(10);
      final JTextField newValueField = new JTextField(10);

      JPanel panel = new JPanel();
      panel.add(spinner);
      panel.add(new JLabel("old value:"));
      panel.add(oldValueField);
      panel.add(new JLabel("new value:"));
      panel.add(newValueField);

      myModel.addPropertyChangeListener(new PropertyChangeListener() {
         public void propertyChange(PropertyChangeEvent evt) {
            // checking the property name is overkill here, but is a good habit
            // to get into, especially if listening to more than one property.
            if (evt.getPropertyName().equals(MySpinnerNumberModel.VALUE)) {
               oldValueField.setText(evt.getOldValue().toString());
               newValueField.setText(evt.getNewValue().toString());
            }
         }
      });

      JFrame frame = new JFrame("TestSpinnerPropChange");
      frame.getContentPane().add(panel);
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/6969740

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档