You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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方法无法访问)。

具体修复步骤

  1. 修复变量作用域问题
    将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();
   }
   // ... 其他代码不变
}
  1. 使用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();
}
  1. 可选:若坚持使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 09:05:33