【问题标题】:How to define a formatted text field in Swing so that the format restrictions are applied as you type?如何在 Swing 中定义格式化文本字段,以便在您键入时应用格式限制?
【发布时间】:2013-12-07 04:31:24
【问题描述】:

我需要 JFrame 上的这样一个数字文本字段

  1. 用小数点后两位数限制输入 点
  2. 列出分隔每三位数字的数字,即 1 234 567,89。
  3. 号码立即以正确的格式显示 打字时

我尝试使用 JFormattedTextField:

    NumberFormat nf = NumberFormat.getNumberInstance();
    nf.setMaximumFractionDigits(2);
    NumberFormatter numFormater = new NumberFormatter(nf);
    field1 = new javax.swing.JFormattedTextField(numFormater);

但是,格式限制仅适用于焦点离开组件时,这是一个问题。我希望用户能够在字段中仅键入数字和分隔符,并且在字段中输入每个 3-d 数字后立即放置一个空格分隔符。

我可以在 C# 中通过指定字段的属性来做到这一点。在 Swing 中执行此操作的干净方法是什么? 谢谢。

【问题讨论】:

    标签: java swing number-formatting jformattedtextfield


    【解决方案1】:

    如何在字段中添加一个 KeyListener 并在键入键时重新格式化?

    【讨论】:

    • 调用重新格式化的正确方法是什么?在组件之间切换焦点看起来不太干净,并且存在插入符号错位的问题。
    【解决方案2】:
    • 其中一种方法是使用InternationalFormatter,这是对Number or DecimalFormatter 的附加Formatter

    • JFormattedTextField 中的每个限制对用户输入都有副作用,例如CaretSelection

    • 适当的方法可以是使用组合DocumentFilterDocumentListener 添加到JFormattedTextField 和普通Number or DecimalFormatter,没有任何限制,所有解决方法都将设置在DocumentFilter(指定用于更改在Document) 内和DocumentListener(在文档外)

    例如提到InternationalFormatter

    import java.awt.*;
    import java.math.*;
    import java.text.*;
    import javax.swing.*;
    import javax.swing.JFormattedTextField.AbstractFormatter;
    import javax.swing.JFormattedTextField.AbstractFormatterFactory;
    import javax.swing.text.InternationalFormatter;
    
    public class DocumentListenerAdapter {
    
        public DocumentListenerAdapter() {
            JFrame frame = new JFrame("AbstractTextField Test");
            final JFormattedTextField textField1 = new JFormattedTextField(new Float(10.01));
            textField1.setFormatterFactory(new AbstractFormatterFactory() {
                @Override
                public AbstractFormatter getFormatter(JFormattedTextField tf) {
                    NumberFormat format = DecimalFormat.getInstance();
                    format.setMinimumFractionDigits(2);
                    format.setMaximumFractionDigits(2);
                    format.setRoundingMode(RoundingMode.HALF_UP);
                    InternationalFormatter formatter = new InternationalFormatter(format);
                    formatter.setAllowsInvalid(false);
                    formatter.setMinimum(0.0);
                    formatter.setMaximum(1000.00);
                    return formatter;
                }
            });
            NumberFormat numberFormat = NumberFormat.getNumberInstance();
            numberFormat.setMaximumFractionDigits(2);
            numberFormat.setMaximumFractionDigits(2);
            numberFormat.setRoundingMode(RoundingMode.HALF_UP);
            final JFormattedTextField textField2 = new JFormattedTextField(numberFormat);
            textField2.setValue(new Float(10.01));
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(textField1, BorderLayout.NORTH);
            frame.add(textField2, BorderLayout.SOUTH);
            frame.setVisible(true);
            frame.pack();
        }
    
        public static void main(String args[]) {
            java.awt.EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new DocumentListenerAdapter();
                }
            });
        }
    }
    

    例如JSpinner (editor is JFormattedTextField) with very simple DocumentFilter

    【讨论】:

    • 相当完整的答案+1 :)
    • @mKorbel 在这个解决方案中有一个奇怪的效果:在第 4、第 7、... 位之后添加分隔符后,插入符号恰好放错了位置。如果输入 123123123,则输入结果为 123 232 311,00(语言环境:ru)。不幸的是,这很不方便,我想在某个地方的实现中存在错误?
    猜你喜欢
    • 1970-01-01
    • 2017-07-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多