如何使用KeyListener在2行1列GridLayout的指定单元格显示JTextField输入校验消息
问题场景与修正实现
背景
基于Java Swing开发界面,采用2行1列GridLayout布局,要求:
- 第一行放置带输入框的参数输入面板
- 第二行放置红色加粗的输入校验错误提示
- 输入框绑定监听器,用户输入时实时触发校验、更新提示状态
现有代码实现
输入面板初始化
JPanel xInputPanelLeft = new JPanel(); xTextField1 = new JTextField(5); xInputPanelLeft.add(new JLabel("Center X: ")); xInputPanelLeft.add(xTextField1); xTextField1.addKeyListener(this);
提示面板初始化
errorPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); errorMessage = new JLabel(); errorMessage.setFont(new Font("Calibri",Font.BOLD,15)); errorMessage.setForeground(Color.RED);
KeyListener事件逻辑
三个重写方法keyTyped、keyPressed、keyReleased逻辑完全一致:
- 判断事件源为
xTextField1时进入处理分支 - 尝试将输入框文本转为整数,赋值给
drawCircle.centerX1 - 捕获数字格式转换异常时,设置提示文本为
Invalid Input Type - 将
redraw按钮设置为可用状态
对应代码:
@Override public void keyTyped(KeyEvent e) { if (e.getSource()==xTextField1){ try{ drawCircle.centerX1 = Integer.parseInt(xTextField1.getText()); } catch (NumberFormatException error){ errorMessage.setText("Invalid Input Type"); } redraw.setEnabled(true); } } @Override public void keyPressed(KeyEvent e) { if (e.getSource()==xTextField1){ try{ drawCircle.centerX1 = Integer.parseInt(xTextField1.getText()); } catch (NumberFormatException error){ errorMessage.setText("Invalid Input Type"); } redraw.setEnabled(true); } } @Override public void keyReleased(KeyEvent e) { if (e.getSource()==xTextField1){ try{ drawCircle.centerX1 = Integer.parseInt(xTextField1.getText()); } catch (NumberFormatException error){ errorMessage.setText("Invalid Input Type"); } redraw.setEnabled(true); } }
存在的缺陷
- 组件挂载链路缺失:
errorMessage未被添加到errorPanel,两个面板(输入区、提示区)也未被挂载到采用2行1列GridLayout的顶层容器,提示组件不会出现在第二行单元格 - 监听器时序错误:
keyTyped触发时输入框文本尚未完成更新,读取到的旧文本会导致校验结果滞后、提示不准确 - 代码冗余:三个KeyListener回调方法逻辑完全重复,无差异化处理
- 异常分支逻辑不全:校验通过时未清空原有错误提示,会出现提示内容残留
修正方案
- 补全组件挂载:将
errorMessage添加到errorPanel,再将输入面板、errorPanel按顺序添加到采用new GridLayout(2,1)的顶层容器,顺序添加即自动对应第一行、第二行单元格 - 替换KeyListener实现:改用
DocumentListener监听输入框的内容变化,该监听在输入框文本完成更新后触发,不会出现时序错位问题,同时可以抽离公共校验逻辑,消除冗余代码
示例实现:xTextField1.getDocument().addDocumentListener(new DocumentListener() { private void doValidate() { String input = xTextField1.getText().trim(); try { drawCircle.centerX1 = Integer.parseInt(input); errorMessage.setText(""); } catch (NumberFormatException e) { if (!input.isEmpty()) { errorMessage.setText("Invalid Input Type"); } else { errorMessage.setText(""); } } redraw.setEnabled(true); } @Override public void insertUpdate(DocumentEvent e) { doValidate(); } @Override public void removeUpdate(DocumentEvent e) { doValidate(); } @Override public void changedUpdate(DocumentEvent e) { doValidate(); } });
内容的提问来源于stack exchange,提问作者Kingsley Yong
相关产品推荐
相关产品推荐

