当前位置: 首页 > 知识库问答 >
问题:

JTextField,用于在覆盖选定内容时自动删除字符

章昊
2023-03-14

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

问题是,一旦我有了4个数字,如果我选择所有数字,并试图通过键入另一个数字来覆盖它们,它不会自动覆盖,也不会执行任何操作,我必须在键盘中显式键入“Backspace”或“Delete”以删除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));
  }

}

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

共有2个答案

匡翰
2023-03-14
匿名用户

扩展Abra的回答:

替换(...)方法中的长度参数包含将被删除的字符数。

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

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

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

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

西门建安
2023-03-14

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

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

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

 类似资料:
  • 我目前在我的应用程序中为谷歌地图设置了一个覆盖图,用于谷歌地图活动。 图像排列完美,但当您离开覆盖区域时,您会看到正常的谷歌地图视图。 我想隐藏除自定义覆盖之外的所有内容,我如何才能做到这一点? 为了防止用户从相机放大的地方缩小并丢失自定义覆盖,我可以将用户锁定在特定gps坐标范围内吗?(自定义覆盖所覆盖的区域)

  • 问题内容: 假设我有一个这样的架构: 如果删除一个人,那么仍然存在孤立的作业,这些作业引用了一个不存在的人,这在数据库中造成了混乱。 有没有一种简单的方法来确保删除一个人时,对该人的所有相应引用也将被删除? 问题答案: 您可以在架构上添加自己的Mongoose 中间件,以将该人从引用该人的所有其他文档中删除。在中间件功能中,就是要删除的文档。

  • 需要根据表单复选框元素添加自定义费用到购物车。基于购物车中产品类别的当前操作非常有效,并增加了自定义送货费,但客户可以选择免费提货。复选框选中交付触发器WooCommerce可以添加自定义费用操作吗? 使用例子从"执行一个动作对复选框选中或未选中的事件在html表单"可以. Change(函数)函数传递(id){如果(this.checked){add_action自定义购物车费用? 选中复选框时

  • 问题内容: 具有运行后自动删除容器的标志。我想知道是否有与docker- compose.yml对应的特定服务配置,因为我在yml中获得的其中一项服务是一个脱离构建的过程,该过程应该只输出编译文件并自行消失。 问题答案: 我没有找到任何选项来帮助您在文件中定义此行为,我认为解释如下: 构建,(重新)创建,启动并附加到服务的容器。 由于您的服务器已构建并且服务已经启动,因此您可以使用和启动/停止服务

  • 本文向大家介绍覆盖Drupal 6自动选择元素验证,包括了覆盖Drupal 6自动选择元素验证的使用技巧和注意事项,需要的朋友参考一下 尽管最近在Drupal 6中创建了一个大型而复杂的表单,但是我遇到了一个问题,这个问题花了我几个小时才能解决,因此我将解决方案发布在这里,以防其他人同样陷入困境。我也将其写下来,这样我就可以记住该策略,以防万一我不得不再次做同样的事情。 我正在做的是创建活动预订表

  • 问题内容: 考虑以下类别: 在某些情况下,需要覆盖自动装配的注射,例如,当Spring无法找到单个注射候选物时。在XML中,我可以有以下示例: 有没有办法用Java Config做同样的事情?以下内容不起作用(我理解原因),因为Spring尝试从myBean方法返回后尝试自动装配该属性,并且该属性失败,并显示NoUniqueBeanDefinitionException: 修改MyBean类并不总