【问题标题】:Java KeyListener ControlJava KeyListener 控件
【发布时间】:2016-02-08 21:36:55
【问题描述】:

我使用 Key Listener 读取来自用户的输入,但我遇到了问题。首先,我读到 JTextField “请输入您的姓名”。如果用户输入名称,例如 John,它将更改为 John。但是如果用户输入了无效字符,例如 "7" 我想写 "Please enter your name" 但它写的是 "Please enter your name7" 。它一直在进行,直到给出正确的输入。我该如何纠正它们??

public void keyTyped(KeyEvent e) {
                int ascii = (int)e.getKeyChar();
                if((ascii >= 65 && ascii <=122) || (ascii <= 351 && ascii >= 199 )){
                    if(TextField1.getText().equals("Please enter your name"))
                        TextField1.setText("");
                }
                else
                    TextField1.setText("Please enter your name");   
            }

【问题讨论】:

    标签: java swing jtextfield keylistener


    【解决方案1】:

    切勿将 KeyListener 与 JTextComponent(如 JTextArea)一起使用。相反,一种选择是使用已添加到组件的 Document 的 DocumentListener 或 DocumentFilter。如果您想完全阻止用户输入无效字符,那么 DocumentFilter 可以很好地工作。另一种选择是将InputVerifier 附加到当用户试图离开文本组件时启动的组件。

    例如

    import java.awt.event.FocusAdapter;
    import java.awt.event.FocusEvent;
    import javax.swing.*;
    import javax.swing.text.JTextComponent;
    
    @SuppressWarnings("serial")
    public class MyTextField extends JPanel {
        private static final String DEFAULT_TEXT = "Please enter your name";
        private static final int COLUMNS = 20;
        private JTextField textField = new JTextField(DEFAULT_TEXT, COLUMNS);
    
        public MyTextField() {
            add(new JLabel("Name:"));
            add(textField);
            add(new JButton("Submit"));
    
            textField.addFocusListener(new TextFocusListener());
            textField.setInputVerifier(new MyInputVerfier());
        }
    
        private class TextFocusListener extends FocusAdapter {
            @Override
            public void focusGained(FocusEvent e) {
                JTextComponent textComp = (JTextComponent) e.getComponent();
                if (textComp != null) {
                    textComp.selectAll(); // so can change all text
                }
                super.focusGained(e);
            }
        }
    
        private class MyInputVerfier extends InputVerifier {
    
            @Override
            public boolean verify(JComponent input) {
                String text = ((JTextComponent) input).getText();
                if (!text.replaceAll("\\d", "").equals(text)) {
                    return false;
                }
                return true;
            }
    
            @Override
            public boolean shouldYieldFocus(JComponent input) {
                if (!verify(input)) {
                    JTextComponent textComp = (JTextComponent) input;
                    textComp.setText(DEFAULT_TEXT);
                    textComp.selectAll();
                    return false;
                }
                return super.shouldYieldFocus(input);
            }
    
        }
    
        private static void createAndShowGui() {
            MyTextField mainPanel = new MyTextField();
    
            JFrame frame = new JFrame("MyTextField");
            frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
            frame.getContentPane().add(mainPanel);
            frame.pack();
            frame.setLocationByPlatform(true);
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    createAndShowGui();
                }
            });
        }
    }
    

    【讨论】:

      【解决方案2】:

      变量名称不应以大写字符开头。

      if((ascii >= 65 && ascii <=122) || (ascii <= 351 && ascii >= 199 )){
      

      不要使用幻数。如果您要检查小写/大写字母字符,请使用 Character 类中的方法,例如 isLetter(...)

      不要使用 KeyListener,它是一个旧 API。 Swing 有更新更好的 API。例如,如果将文本粘贴到文本字段,您的逻辑将不起作用。使用JFormattedTextField 或DocumentFilter 在键入文本时检查有效数据。有关更多信息,请参阅 Swing 教程中关于 How to Write a Document Filter 和 How to Use Text Fields 的部分。

      我不建议在文本字段中放置文本作为提示。如需不同的方法,请查看Text Prompt

      但它写的是“请输入您的姓名7”。

      发生这种情况的原因是 keyTyped 事件是在使用键入的文本更新 Document 之前生成的。要最后执行 setText() 方法,您可以将该语句包装在 SwingUtiltities.invokeLater(...) 中。

      出于上述所有原因,我不推荐这种方法。

      【讨论】:

      • 感谢您的帮助 :) 我在编码时几乎睡着了,所以我错过了规则。我是 Windows Form App 的新手,所以我要学习它们 :) 我将 jtextfield 更改为 formattedfield。我明天继续。非常感谢
      猜你喜欢
      • 2012-08-10
      • 2013-08-31
      • 2023-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-06-04
      • 2013-04-26
      相关资源
      最近更新 更多