2013-12-09 78 views
1

我有一个输入不同形式的相同信息的2 JFormattedTextField。当用户改变另一个时,我希望有一个改变。在使用PropertyChangeListener之前,我已经实现了这样的功能,但是这次我遇到了一个奇怪的错误。当JFrame打开时,为什么此属性更改事件触发?

当我的JFrame打开PropertyChangeListener事件被无缘无故触发。 PropertyChangeEvent上的getNewValue()的值为空。

这里是所有引用我的标签代码:后来

private JFormattedTextField fpsField; 

然后在我的JFrame的构造函数:

fpsField = new JFormattedTextField(NumberFormat.getInstance()); 
fpsField.addPropertyChangeListener("value", new PropertyChangeListener() { 
    public void propertyChange(PropertyChangeEvent arg0) { 
     if(!updatingFPS){ 
      updatingFPS = true; 

      Float fps = (Float) arg0.getNewValue(); 

      long newDelay = Math.round(1000/fps); 
      delayField.setValue(newDelay); 

      updatingFPS = false; 
     } 
    } 
}); 
GridBagConstraints gbc_fpsField = new GridBagConstraints(); 
gbc_fpsField.insets = new Insets(0, 0, 5, 0); 
gbc_fpsField.fill = GridBagConstraints.HORIZONTAL; 
gbc_fpsField.gridx = 1; 
gbc_fpsField.gridy = 0; 
monitorPreferencesPane.add(fpsField, gbc_fpsField); 
fpsField.setColumns(10); 

正如你可以看到我不代码和事件设定的值被调用(并生成一个NullPointerException),然后我有机会输入任何内容。我还没有为delayField编写监听器。

回答

3

由于缺省值为null,打开JFrame时激发的焦点事件将触发属性更改事件,因为无法充分比较null。可能的解决方案之后,请参阅下面代码的完整说明。

一个解决方案摆脱了NPE的是加入PropertyChangeListener因为这样做的JFrame打开时将不发射PropertyChange事件之前设置的默认值您fpsField

JFormattedTextField fpsField = new JFormattedTextField(NumberFormat.getInstance()); 
fpsField.setValue(0); 

另一种解决办法,如果你不能设置默认值,是检查是否在事件新旧值更新delayField之前实际上是不同的。当JFrame开放时,它们都是null

原因是触发事件是因为FocusEvent,其中的原因是ACTIVATION由您JFormattedTextField发射和处理,这就要求

/** 
* Processes any focus events, such as 
* <code>FocusEvent.FOCUS_GAINED</code> or 
* <code>FocusEvent.FOCUS_LOST</code>. 
* 
* @param e the <code>FocusEvent</code> 
* @see FocusEvent 
*/ 
protected void processFocusEvent(FocusEvent e) { 
    super.processFocusEvent(e); 

// ignore temporary focus event 
if (e.isTemporary()) { 
    return; 
} 

    if (isEdited() && e.getID() == FocusEvent.FOCUS_LOST) { 
    InputContext ic = getInputContext(); 
    if (focusLostHandler == null) { 
    focusLostHandler = new FocusLostHandler(); 
    } 

    // if there is a composed text, process it first 
    if ((ic != null) && composedTextExists) { 
    ic.endComposition(); 
    EventQueue.invokeLater(focusLostHandler); 
    } else { 
    focusLostHandler.run(); 
    } 
    } 
    else if (!isEdited()) { 
     // reformat 
     setValue(getValue(), true, true); 
    } 
} 

/** 
* Does the setting of the value. If <code>createFormat</code> is true, 
* this will also obtain a new <code>AbstractFormatter</code> from the 
* current factory. The property change event will be fired if 
* <code>firePC</code> is true. 
*/ 
private void setValue(Object value, boolean createFormat, boolean firePC) { 

因为firePCtrue,它会在value上触发PropertyChange事件。

最后,由于默认值是null,病情居然触发事件

/** 
* Support for reporting bound property changes for Object properties. 
* This method can be called when a bound property has changed and it will 
* send the appropriate PropertyChangeEvent to any registered 
* PropertyChangeListeners. 
* 
* @param propertyName the property whose value has changed 
* @param oldValue the property's previous value 
* @param newValue the property's new value 
*/ 
protected void firePropertyChange(String propertyName, 
            Object oldValue, Object newValue) { 
    PropertyChangeSupport changeSupport; 
    synchronized (getObjectLock()) { 
     changeSupport = this.changeSupport; 
    } 
    if (changeSupport == null || 
     (oldValue != null && newValue != null && oldValue.equals(newValue))) { 
     return; 
    } 
    changeSupport.firePropertyChange(propertyName, oldValue, newValue); 
} 

将触发它,oldValuenewValue既是null

+0

我认为文档是关于如何将值集格式化为一个'字符串'并且与实际值无关。在even之前设置该值可能会解决异常,我也可以简单地检查一个空值。我更多地问这个问题并不是因为我无法解决这个问题,而是因为我不明白发生了什么,想要什么。 – Fr33dan

+0

终于找到了整个事件链。 –

+0

我去吃午饭,回到关于这个问题的文章。令人赞叹的工作。 – Fr33dan

相关问题