Java 如何在Swing中定义格式化文本字段,以便在键入时应用格式限制?

Java 如何在Swing中定义格式化文本字段,以便在键入时应用格式限制?,java,swing,number-formatting,jformattedtextfield,Java,Swing,Number Formatting,Jformattedtextfield,我需要在JFrame上有这样一个数字文本字段 将输入限制为小数点后两位数的数字 点 列出每三位数字分隔的数字,即1 234 567,89. 数字立即以正确的格式显示 打字时 我尝试使用JFormattedTextField: NumberFormat nf = NumberFormat.getNumberInstance(); nf.setMaximumFractionDigits(2); NumberFormatter numFormater = new Number

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

  • 将输入限制为小数点后两位数的数字 点
  • 列出每三位数字分隔的数字,即1 234 567,89.
  • 数字立即以正确的格式显示 打字时
  • 我尝试使用JFormattedTextField:

        NumberFormat nf = NumberFormat.getNumberInstance();
        nf.setMaximumFractionDigits(2);
        NumberFormatter numFormater = new NumberFormatter(nf);
        field1 = new javax.swing.JFormattedTextField(numFormater);
    
    但是,格式限制仅在焦点离开组件时适用,这是一个问题。我希望用户能够在字段中只键入数字和delimeter,并在字段中输入每个三维数字后放置一个空格delimeter

    我可以在C#中通过指定字段的属性来实现这一点。在Swing中,什么是干净的方法?
    谢谢。

    将KeyListener添加到字段并在键入密钥时重新格式化如何?

    将KeyListener添加到字段并在键入密钥时重新格式化如何?

    • 其中一种方法是使用
      InternationalFormatter
      ,这是
      Number或DecimalFormatter

    • 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();
                  }
              });
          }
      }
      
    • JFormattedTextField
      中的每个限制对用户输入都有副作用,例如
      插入符号
      选择
      ,等等

    • 适当的方法可以是使用组合
      DocumentFilter
      DocumentListener
      添加到
      JFormattedTextField
      和普通
      数字或十进制格式
      ,没有任何限制,所有解决方法都将在
      DocumentFilter
      中设置(指定用于
      文档
      内部的更改)和
      文档监听器
      (文档外部)

    例如提到的
    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();
                }
            });
        }
    }
    
    例如

    • 其中一种方法是使用
      InternationalFormatter
      ,这是
      Number或DecimalFormatter

    • 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();
                  }
              });
          }
      }
      
    • JFormattedTextField
      中的每个限制对用户输入都有副作用,例如
      插入符号
      选择
      ,等等

    • 适当的方法可以是使用组合
      DocumentFilter
      DocumentListener
      添加到
      JFormattedTextField
      和普通
      数字或十进制格式
      ,没有任何限制,所有解决方法都将在
      DocumentFilter
      中设置(指定用于
      文档
      内部的更改)和
      文档监听器
      (文档外部)

    例如提到的
    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();
                }
            });
        }
    }
    

    例如,

    相当完整的答案+1:)@mKorbel此解决方案中有一个奇怪的效果:在第4、7、…位后添加delimeter后,插入符号碰巧放错了位置。如果键入123123,输入的结果是123 232 311,00(区域设置:ru)。不幸的是,这非常不方便,我想在某个地方的实现中有一个bug?相当完整的答案+1:)@mKorbel此解决方案中有一个奇怪的效果:在第4、7次之后添加delimeter后,。。。数字,插入符号恰好放错了位置。如果键入123123,则输入结果为123232 311,00(区域设置:ru)。不幸的是,这非常不方便,我想在实现中的某个地方有一个bug?调用重新格式化的正确方法是什么?在组件之间切换焦点似乎不干净,并且存在插入符号错位的问题。调用重新格式化的正确方法是什么?在组件之间切换焦点似乎不干净,并且存在插入符号错位的问题。