Java Swing:初始化Authentication类后ATM_Interface无法检测键盘事件
问题:ATM模拟器中添加Authentication组件后ATM_Interface无法捕获键盘事件
我正在开发一款ATM模拟器,希望按下ENTER键时验证PIN码。但遇到问题:初始化Authentication类后,ATM_Interface类无法检测到键盘事件。已尝试用requestFocusInWindow()和setFocusable()设置焦点,但问题仍未解决。
相关代码如下:
Main类
public class Main{ public static void main(String[] args){ JFrame frame = new JFrame(); ATM_Interface atm=new ATM_Interface(); frame.setVisible(true); frame.setDefaultCloseOperation(3); frame.setLayout(null); frame.add(atm); frame.pack(); } }
ATM_Interface类
public class ATM_Interface extends JPanel { static String Status=""; public ATM_Interface(){ this.setPreferredSize(new Dimension(200,200)); this.setBackground(Color.blue); this.setBounds(115,67,340,340); this.addKeyListener(new keyAdapter()); this.setFocusable(true); Authentication auth = new Authentication(); this.requestFocusInWindow(); } class keyAdapter extends KeyAdapter{ @Override public void keyPressed(KeyEvent e){ switch(Status){ case "authentication": break; default: add(auth); Status="authentication"; } System.out.println("test"); } } }
Authentication类
public class Authentication extends JPanel { JTextField input = new JTextField(); public Authentication(){ input.setPreferredSize(new Dimension(100,50)); this.add(input); } public boolean getAcces(){ if(input.getText().equals("0234")){ return true; } else return false; } }
解决方案
核心问题分析
当把Authentication组件添加到ATM_Interface后,其内部的JTextField会自动获取焦点,而KeyListener仅在组件拥有焦点时才会触发键盘事件,这就导致ATM_Interface的键盘事件无法被检测到。此外代码中还存在变量作用域错误(auth是构造函数局部变量,keyPressed方法无法访问)。
具体修复步骤
- 修复变量作用域问题
将Authentication auth从构造函数的局部变量改为ATM_Interface的成员变量,确保keyPressed方法能正常访问:
public class ATM_Interface extends JPanel { static String Status=""; private Authentication auth; // 改为成员变量 public ATM_Interface(){ this.setPreferredSize(new Dimension(200,200)); this.setBackground(Color.blue); this.setBounds(115,67,340,340); this.setFocusable(true); auth = new Authentication(); // 初始化成员变量 this.requestFocusInWindow(); } // ... 其他代码不变 }
- 使用Key Bindings替代KeyListener
Key Bindings不需要组件拥有焦点就能响应键盘事件,更适合这类场景。修改ATM_Interface的构造函数,添加ENTER键的绑定:
public ATM_Interface(){ this.setPreferredSize(new Dimension(200,200)); this.setBackground(Color.blue); this.setBounds(115,67,340,340); this.setFocusable(true); auth = new Authentication(); // 绑定ENTER键 InputMap inputMap = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); ActionMap actionMap = this.getActionMap(); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "validatePin"); actionMap.put("validatePin", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { switch(Status){ case "authentication": // 验证PIN码 if(auth.getAcces()){ System.out.println("PIN验证通过"); } else { System.out.println("PIN错误"); } break; default: add(auth); Status="authentication"; // 添加后让输入框自动获取焦点,方便用户输入 auth.input.requestFocusInWindow(); break; } System.out.println("test"); } }); this.requestFocusInWindow(); }
- 可选:若坚持使用KeyListener
如果一定要用KeyListener,需要在添加Authentication组件后,强制让ATM_Interface重新获取焦点,同时修改Authentication组件,让其内部的JTextField不自动抢焦点:
- 在Authentication构造函数中添加:
input.setFocusable(false);(但这样用户无法输入PIN,显然不合适,因此不推荐这种方式)
优化后的完整ATM_Interface类
import javax.swing.*; import java.awt.*; import java.awt.event.*; public class ATM_Interface extends JPanel { static String Status = ""; private Authentication auth; public ATM_Interface() { this.setPreferredSize(new Dimension(200, 200)); this.setBackground(Color.blue); this.setBounds(115, 67, 340, 340); this.setFocusable(true); auth = new Authentication(); // 配置ENTER键的Key Binding InputMap inputMap = this.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); ActionMap actionMap = this.getActionMap(); inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "handleEnter"); actionMap.put("handleEnter", new AbstractAction() { @Override public void actionPerformed(ActionEvent e) { switch (Status) { case "authentication": if (auth.getAcces()) { System.out.println("PIN验证通过"); // 这里可以添加验证通过后的逻辑,比如进入主界面 } else { System.out.println("PIN码错误,请重新输入"); auth.input.setText(""); } break; default: add(auth); Status = "authentication"; auth.input.requestFocusInWindow(); // 让输入框获取焦点,方便用户输入 break; } System.out.println("test"); } }); this.requestFocusInWindow(); } }
内容的提问来源于stack exchange,提问作者Oussama Mahjour
相关产品推荐
相关产品推荐

