1

我有一个 2 JFormattedTextFields,它以不同的形式输入相同的信息。当用户更改另一项时,我希望进行一项更改。在使用 s 之前我已经实现了类似的东西PropertyChangeListener,但是这次我遇到了一个奇怪的错误。

当我JFrame打开PropertyChangeListener事件时,没有明显的原因触发。getNewValue()on 的值为PropertyChangeEvent空。

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

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

4

1 回答 1

3

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

摆脱 NPE 的一种解决方案是fpsField在添加之前为您设置一个默认值,PropertyChangeListener因为这样做不会在打开PropertyChange时触发事件。JFrame

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

如果您无法设置默认值,另一种解决方案是在更新您的delayField. 他们都是开场null时。JFrame

触发事件的原因是因为 a FocusEvent,原因ACTIVATION被触发并由 your 处理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,它会触发PropertyChange事件value

最后,由于默认值为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);
}

将解雇它,oldValue并且newValue两者兼而有之null

于 2013-12-09T16:59:12.493 回答