【问题标题】:Deleting last keystroke in JTextField if invalid如果无效,则删除 JTextField 中的最后一次击键
【发布时间】:2012-08-06 22:10:29
【问题描述】:

在我的第一个程序上工作。我想出了如何识别我不想输入的字符。我想知道如何删除最后输入的字符,以便从用户的角度来看,它会显示为只能输入数字。

@Override
public void keyPressed(KeyEvent e) {
    char keyChar = e.getKeyChar();;
    char[] badCharArray = "abcdefghijklmnopqrstuvwxyz-`~!@#$%^&*()[]{}<>_+=|\"':;?/ ".toCharArray();
        for (int i = 0; i < badCharArray.length; i++) {
            if (badCharArray[i] == keyChar) {
                System.out.print(badCharArray[i] + " bad\n");
                hourlyWageInput.setBackground(Color.RED);
                } 
            }
        }

谢谢。

【问题讨论】:

  • e.Consume() 会阻止它被传递到文本字段,但是没有理由把它变成红色......

标签: java swing jframe jtextfield


【解决方案1】:

最简单的方法是使用 JFormattedTextField 而不是 JTextField。

NumberFormat format = NumberFormat.getNumberInstance();
format.setMinimumFractionDigits(2); // eventually maximum fraction digits

JFormattedTextField fld = new JFormattedTextField(format);

【讨论】:

    【解决方案2】:

    在这种情况下,您应该避免使用keyListeners。如果用户将文本粘贴到字段中会发生什么。不会通知keyListener,允许插入无效字符。

    您最好使用DocumentFilter 过滤掉您不想要的任何无效字符。

    查看Implementing a DocumentFilter 了解更多信息,查看DocumentFilter 了解一些不错的示例

    【讨论】:

    • 按键监听器确实检测到 ctrl + v,但是,如果他添加右键菜单,是的,它会在那里失败,但默认情况下不在 JTextField 上。
    • @Alex:这是迄今为止更好的答案。 1+。 DocumentFilters 将允许修改输入的数据在显示之前,在验证之前。
    • @HovercraftFullOfEels 是的,我只是说这在某些情况下会失败(他没有);但是,我的 99% 的时间仍然可以工作。无需投票...
    • @Alex:您不应该容忍在 Swing 应用程序中使用 KeyListener,因为它们确实应该被避免。是的,它们是一种快速且“简单”的解决方案,但它们的级别太低了——尤其是当有更强大的更高级别的解决方案可用时。同样,它们与复制粘贴没有任何关系,它们无法用于替代输入设备,在这种情况下它们是错误的。期间。
    • @AlexColeman setText 怎么样? KeyListener 根本不会收到通知吗?我同意,这个问题是关于 KeyListener 实现的,但我们也应该鼓励良好的做法,我也觉得只是回答问题的陷阱,虽然你的解决方案有效,但它很容易出现文档突变异常跨度>
    【解决方案3】:

    只需将它的文本设置为当前文本,插入符号位置之前没有字符


        @Override
        public void keyReleased(KeyEvent paramKeyEvent) {
            char keyChar = paramKeyEvent.getKeyChar();
            char[] badCharArray = "abcdefghijklmnopqrstuvwxyz-`~!@#$%^&*()[]{}<>_+=|\"':;?/ ".toCharArray();
                for (int i = 0; i < badCharArray.length; i++) {
                    if (badCharArray[i] == keyChar) {
                        int caret = field.getCaretPosition()-1;
                        System.out.print(badCharArray[i] + " bad\n");
                        field.setText(field.getText().substring(0, caret) + 
                                field.getText().substring(caret+1));
                        field.setCaretPosition(caret);
                        } 
                }
        }
    

    把它设置为红色,好像你要自动更正它一样,在那里没有意义(也许将它设置为显示红色一秒钟?)


    实际上,唯一的问题是,如果他们持有无效的密钥,它只会删除最后一个;以下应该会更好,并且不会移动插入符号:P

            boolean held = false;
            private int oldCaret = 1;
            @Override
            public void keyPressed(KeyEvent e) {
                if(! held) {
                    oldCaret=field.getCaretPosition();
                    System.out.println(oldCaret);
                }
                held = true;
    
            }
            @Override
            public void keyReleased(KeyEvent paramKeyEvent) {
                char keyChar = paramKeyEvent.getKeyChar();
                char[] badCharArray = "abcdefghijklmnopqrstuvwxyz-`~!@#$%^&*()[]{}<>_+=|\"':;?/ ".toCharArray();
                for (int i = 0; i < badCharArray.length; i++) {
                    if(field.getText().contains(badCharArray[i]+"")) {
                        field.setText(field.getText().replace(badCharArray[i]+"", ""));
                        field.setCaretPosition(oldCaret);
                    }
                }
    
                held=false;
            }
    

    【讨论】:

    • @DavidTunnell:这不是正确的答案,您不想使用 KeyListener。正确且更可靠的答案是按照 MadProgrammer 的答案使用 DocumentFilter。它可以处理复制和粘贴以及其他非键盘输入。
    • @DavidTunnell 顺便说一句,您需要在 char[]、A-Z 中添加大写字符,而不仅仅是 a-z
    【解决方案4】:

    这里是JTextField的创建:

    hourlyWageInput = new JTextField("7.25");
    DocumentFilter filter = new UppercaseDocumentFilter();
    ((AbstractDocument) hourlyWageInput.getDocument()).setDocumentFilter(filter);
    hourlyWageInput.setHorizontalAlignment(JTextField.CENTER);
    add(hourlyWageInput);
    

    这是我的 DocumentFilter:

    import javax.swing.text.BadLocationException;
    import javax.swing.text.DocumentFilter;
    
    public class UppercaseDocumentFilter extends DocumentFilter {
    
         public void replace(DocumentFilter.FilterBypass fb, int offset, int length,
              String text, javax.swing.text.AttributeSet attr)
    
              throws BadLocationException {
                   fb.insertString(offset, text.replaceAll("\\D", ""), attr);   
         }
    }
    

    这很有效,会自动从 JTextField 中删除所有字母和字符。所以谢谢你,这肯定是最好的。

    但是,我想知道是否有人知道一个地方有所有类似于“\D”的命令。我花了一段时间才找到正确的信息。

    此外,我现在拥有的代码也可以防止 .不是我在使用双打时需要的类型。有什么想法吗?

    感谢大家的帮助,今天我学到了很多东西,真是太棒了。连续编码 13 小时。

    【讨论】:

      猜你喜欢
      • 2010-11-27
      • 2017-09-10
      • 1970-01-01
      • 2014-02-08
      • 2012-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多