【问题标题】:JTextField to remove characters automatically when overwritting selectedJTextField 在覆盖选中时自动删除字符
【发布时间】:2019-03-26 17:45:28
【问题描述】:

我正在使用 Java,并且我有一个只能有 4 位数字的 JTextField。我正在使用扩展 DocumentFilter 的类来过滤掉任何其他字符,并将字符数限制为 4。

问题是,一旦我有 4 位数字,如果我选择所有数字并尝试通过键入另一个数字来覆盖它们,它不会自动覆盖并且什么都不做,我必须 明确地 输入在我的键盘上“退格”或“删除”以删除 4 位数字,然后(一旦字段被清除)我可以再次输入。

我怎样才能让 JTextField 充当操作系统的其余部分,一旦我选择了一些文本,如果我输入一个字符,它就会“删除所有,然后写入该字符”(它替换内容)。

我有一个辅助类,JustLimitDigitFilter.java:

import javax.swing.text.DocumentFilter;
import javax.swing.text.BadLocationException;

import java.awt.Toolkit;

import javax.swing.text.AttributeSet;

public class JustLimitDigitFilter extends DocumentFilter {

  int limit;

  public JustLimitDigitFilter(int limit) {
    this.limit = limit;
  }

  @Override
  public void insertString(DocumentFilter.FilterBypass fb, int offset, String text, AttributeSet attr) throws BadLocationException {

    // if (text == null) {
    //   return;
    // }
    String str = text.replaceAll("\\D", "");
    if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
      super.insertString(fb, offset, str, attr);
    } else {
      Toolkit.getDefaultToolkit().beep();
    }

  }

  @Override
  public void replace(DocumentFilter.FilterBypass fb, int offset, int length, String text, AttributeSet attr)
      throws BadLocationException {

    // if (text == null) {
    //   return;
    // }
    String str = text.replaceAll("\\D", "");
    if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
      super.replace(fb, offset, length, str, attr);
    } else {
      Toolkit.getDefaultToolkit().beep();
    }

  }

}

还有主类App.java

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import javax.swing.JTextField;
import javax.swing.text.AbstractDocument;
import javax.swing.text.DocumentFilter;

public class App {

  private JFrame frame;
  private JTextField textField;

  /**
   * Launch the application.
   */
  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      public void run() {
        try {
          App window = new App();
          window.frame.setVisible(true);
        } catch (Exception e) {
          e.printStackTrace();
        }
      }
    });
  }

  /**
   * Create the application.
   */
  public App() {
    initialize();
  }

  /**
   * Initialize the contents of the frame.
   */
  private void initialize() {
    frame = new JFrame();
    frame.setBounds(100, 100, 191, 96);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.getContentPane().setLayout(null);

    JPanel panel = new JPanel();
    panel.setBounds(6, 6, 179, 62);
    frame.getContentPane().add(panel);
    panel.setLayout(null);

    textField = new JTextField();
    textField.setBounds(6, 6, 167, 26);
    panel.add(textField);
    textField.setColumns(10);

    // without this code below this, the textfield is “normal” when
    // something is selected if I write it overwrites the selection

    AbstractDocument doc = (AbstractDocument) textField.getDocument();
    doc.setDocumentFilter(new JustLimitDigitFilter(4));
  }

}

欢迎任何建议,因为我是新手,除了我明确表示的疑问。

【问题讨论】:

    标签: java swing user-interface windowbuilder documentfilter


    【解决方案1】:

    DocumentFilter 类中的方法replace() 实际上执行两个操作。首先它删除从offset 开始的length 字符,然后在offset 处插入text。因此,当 JTextField 包含最大允许字符数时,replace() 方法中的以下行不会导致任何事情发生...

    if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit) {
    

    如果JTextField 已满,则其长度将是最大字符数,因此添加str 的长度将总是大于limit

    【讨论】:

    • 不错!我仍然不确定删除if。你会怎么解决呢?
    • 您需要检查文本的final长度是否在限制范围内。最终长度是当前长度减去要删除的字符数加上要插入的文本的长度。
    【解决方案2】:

    扩展 Abra 的答案:

    replace(...) 方法中的“length”参数包含要删除的字符数。

    因此您可以将 if 语句更改为:

    //if (!str.isEmpty() && (fb.getDocument().getLength() + str.length()) <= limit)
    if (!str.isEmpty() && (fb.getDocument().getLength() + str.length() - length) <= limit)
    

    在此更改之后,您可以将insert(...) 方法简化为:

    @Override
    public void insertString(FilterBypass fb, int offset, String text, AttributeSet attributes)
        throws BadLocationException
    {
        replace(fb, offset, 0, text, attributes);
    }
    

    【讨论】:

    • 感谢明确的代码,但他是第一个(至少在评论中),所以我会接受他的。无论如何,+1。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-06
    • 2010-11-27
    相关资源
    最近更新 更多