Java 从JFormattedTextField中排除零

Java 从JFormattedTextField中排除零,java,swing,jformattedtextfield,Java,Swing,Jformattedtextfield,我有一个由创建的JFormattedTextField JFormattedTextField(NumberFormat.getInstance); 我想增强它的行为,这样如果用户 输入一个零,该字段失去焦点,它的反应与用户输入的完全相同,例如“foo” 使用InputVerifier以某种方式破坏了还原行为,并且使用DecimalFormat的自定义子类在输入零时没有还原,而是清除了字段。 (我所说的零是指解析为BigDecimal.zero)的任何东西) 我使用的代码是: new De

我有一个由创建的
JFormattedTextField

JFormattedTextField(NumberFormat.getInstance);  
我想增强它的行为,这样如果用户 输入一个零,该字段失去焦点,它的反应与用户输入的完全相同,例如“foo”

使用
InputVerifier
以某种方式破坏了还原行为,并且使用
DecimalFormat
的自定义子类在输入零时没有还原,而是清除了字段。
(我所说的零是指解析为
BigDecimal.zero
)的任何东西)

我使用的代码是:

new DecimalFormat(){
{
    setParseBigDecimal(true);
}
public Number parse(String txt, ParsePosition pos){
     BigDecimal num = (BigDecimal) super.parse(txt, pos);
     if(num == null || num.compareTo(BigDecimal.ZERO) == 0)
          return null;
     else return num;
}

当时不接受零,但该字段仅在输入的字母上恢复。

您可以添加一个
FocusListener
来执行与内部操作类似的检查:

JFormattedTextField ftf = new JFormattedTextField(NumberFormat.getInstance());
ftf.addFocusListener(new FocusAdapter() {

    @Override
    public void focusLost(FocusEvent e) {

        Object lastValid = ftf.getValue();
        try {
            ftf.commitEdit();
        } catch (ParseException e1) {
            ftf.setValue(lastValid);
        }
        Object newValue = ftf.getValue();
        if (newValue instanceof Long)
            if ((Long) newValue == 0l)
                ftf.setValue(lastValid);
    }
});
关于这一办法的说明:
  • JFormattedTextField
    有一个
    focusLostBehavior
    ,它指示如何处理焦点丢失。我假设它总是
    COMMIT\u或\u REVERT
    (默认值)

  • 如果在文本字段中注册了
    PropertyChangeListener
    ,请小心,因为我没有仔细处理触发它的事件。虽然无法解析的输入将“立即”还原(且不会触发
    PropertyChangeEvent
    事件),但解析为
    0
    的值将首先提交(并触发
    PropertyChangeEvent
    ),然后才还原(再次触发
    PropertyChangeEvent

关于其他办法的说明:
  • 虽然我认为这是最直接的方法,但几乎可以肯定还有其他方法可以实现这一点,包括扩展和重写某些方法。从文本字段本身到为其选择的格式的层次结构可能有点复杂,可以在某些步骤中进行修改,但应注意不要破坏任何内容

  • 输入验证也可以工作,但它的行为不同——它保持焦点直到输入被验证,而不是允许其丢失和恢复。这最终是程序员的选择


将类似@user1803551的代码放入
PropertyChangeListener
中效果更好-之前,当表单中有一个默认按钮时,点击“返回”会出现问题-它将收到“已执行的操作”,而用户无需更改输入值。另外,我们没有额外的变量

DecimalFormat format = new DecimalFormat();
format.setParseBigDecimal(true);
JFormattedTextField ftf = new JFormattedTextField(format):
ftf.addPropertyChangeListener(new PropertyChangeListener() {

    public void propertyChange(PropertyChangeEvent evt) {
        if (evt.getPropertyName().equals("value"))
            if ( ((BigDecimal) evt.getNewValue()).compareTo(BigDecimal.ZERO) ==0 )
                ftf.setValue(evt.getOldValue());
        }

    });

“如果用户在字符串中的任何位置输入零”,或者只是
0
?编辑:任何解析为
BigDecimal.zero
的内容,谢谢。但我仍然不明白为什么自定义格式不能。我想,这是可以的,只是需要仔细地做。我的方法类似于在洞上贴一块补丁,而不是缝补。