如何防止JTextField密码校验时将退格、Ctrl等功能键计入输入长度
问题根因
- 你使用了
keyPressed事件触发校验:该事件在按键按下的瞬间触发,此时JTextField的文本内容还未完成更新(输入字符时还没写入组件、退格时还没删除字符),你读取到的始终是修改前的长度。 - 退格、Shift、Ctrl等功能键不会改变文本内容,但依然会触发
keyPressed事件,相当于你拿着旧的文本长度反复做校验,自然会出现长度计算错误的问题。 - 原有校验逻辑存在分支顺序Bug:先判断
length <7,length ==0的分支永远不会触发,因为0也满足小于7的条件。
最优修复方案:使用DocumentListener监听文本真实变化
这个监听器只会在文本内容实际发生变更(输入、删除、粘贴、剪切等操作)时触发,完全不会响应不修改内容的功能键,是Swing文本组件内容校验的标准实现。
示例代码:
// 给JTextField的Document添加监听器,替代KeyListener passwordtext.getDocument().addDocumentListener(new DocumentListener() { // 统一的校验逻辑抽取 private void validatePassword() { String pwd = passwordtext.getText(); int len = pwd.length(); // 先判空 if (len == 0) { passwordMessage.setText(""); return; } // 禁止空格校验 if (pwd.contains(" ")) { passwordMessage.setForeground(Color.RED); passwordMessage.setText("不允许输入空格!"); return; } // 强度校验 if (len >=14) { passwordMessage.setForeground(Color.GREEN); passwordMessage.setText("密码强度:强"); } else if (len >=8) { passwordMessage.setForeground(Color.ORANGE); passwordMessage.setText("密码强度:良好"); } else { passwordMessage.setForeground(Color.RED); passwordMessage.setText("密码最少需要8位字符或数字!"); } } @Override public void insertUpdate(DocumentEvent e) { validatePassword(); } @Override public void removeUpdate(DocumentEvent e) { validatePassword(); } @Override public void changedUpdate(DocumentEvent e) { validatePassword(); } });
注意:使用该方案后可以完全删除原有KeyListener的相关代码,不需要再处理按键事件。
备选方案:如果坚持使用Key事件的修正方法
如果一定要用KeyListener实现,需要做两处修改:
- 把监听事件从
keyPressed改为keyReleased,此时文本内容已经完成更新,拿到的长度是最新值。 - 过滤掉不修改文本的功能键,排除无效触发。
修正后的代码:
public void keyReleased(KeyEvent e) { // 过滤功能键:退格、删除、Shift、Ctrl、Alt、功能键等不改变内容的按键直接跳过校验 int keyCode = e.getKeyCode(); if (keyCode == KeyEvent.VK_SHIFT || keyCode == KeyEvent.VK_CONTROL || keyCode == KeyEvent.VK_ALT || keyCode == KeyEvent.VK_CAPS_LOCK || keyCode == KeyEvent.VK_ESCAPE || keyCode == KeyEvent.VK_F1 || keyCode == KeyEvent.VK_F2 || keyCode == KeyEvent.VK_F3 || keyCode == KeyEvent.VK_F4 || keyCode == KeyEvent.VK_F5 || keyCode == KeyEvent.VK_F6 || keyCode == KeyEvent.VK_F7 || keyCode == KeyEvent.VK_F8 || keyCode == KeyEvent.VK_F9 || keyCode == KeyEvent.VK_F10 || keyCode == KeyEvent.VK_F11 || keyCode == KeyEvent.VK_F12 || keyCode == KeyEvent.VK_WINDOWS || keyCode == KeyEvent.VK_CONTEXT_MENU) { return; } // 空格校验逻辑 if (Character.isWhitespace(e.getKeyChar())) { passwordMessage.setText("不允许输入空格!"); passwordtext.setEditable(false); } else { passwordMessage.setText(""); passwordtext.setEditable(true); } int len = passwordtext.getText().length(); // 修正判断顺序,先判空 if(len == 0) { passwordMessage.setText(""); } else if(len >= 14) { passwordMessage.setForeground(Color.GREEN); passwordMessage.setText("密码强度:强"); } else if(len >= 8) { passwordMessage.setForeground(Color.ORANGE); passwordMessage.setText("密码强度:良好"); } else { passwordMessage.setForeground(Color.RED); passwordMessage.setText("密码最少需要8位字符或数字!"); } }
内容的提问来源于stack exchange,提问作者ABSO
相关产品推荐
相关产品推荐

