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

Java Swing跨类调用JButton的getter/setter报错如何解决

迷宫游戏回退按钮状态控制问题

需求背景

我正在开发一款迷宫游戏,玩家可通过方向键控制角色移动:

  • 程序启动后创建窗体,包含Menu、MazePanel两个JPanel容器
  • Menu面板放置「One step back」按钮,功能为撤销玩家上一步移动
  • 按钮状态规则:
    • 玩家首次移动前、按钮被点击一次后,调用setEnabled(false)设为禁用
    • 按钮点击后,若玩家再次产生移动操作,需重新启用按钮
  • Player类定义布尔变量clickable,初始值为false,玩家每次完成移动后置为true
  • 本次仅需实现玩家移动后激活按钮的逻辑,暂不处理按钮点击后的禁用逻辑

原有代码实现

Main窗体类

public class Main extends JFrame {
    public Main(){
       frame = new JFrame();

       menu = new Menu();
       frame.add(menu);
    
       mazepanel = new MazePanel(frame, menu);
       frame.add(mazepanel);
    }
}

按钮在构造方法中创建并初始化为禁用,同时编写了对应getter/setter:

public class Menu extends JPanel {
    
    private JButton one_step_back;

    public Menu() {
        one_step_back = new JButton("One step back");
        one_step_back.setEnabled(false);
    }

    public JButton getOne_step_back() {
        return one_step_back;
    }

    public void setOne_step_back(JButton one_step_back) {
        this.one_step_back = one_step_back;
    }
}

MazePanel类

初始化时传入frame和menu实例:

public class MazePanel extends JPanel {
    private JFrame frame;
    private JPanel menu;
    
    public MazePanel(JFrame frame, JPanel menu) {
        this.frame = frame;
        this.menu = menu;
        
        play = new Player(); 
    }

    public JPanel getMenu() {
        return menu;
    }

    public void setMenu(JPanel menu) {
        this.menu = menu;
    }
}

Player类

每次按键触发KeyListener调用move方法,仅保留上方向键逻辑:

public class Player implements KeyListener{
    boolean clickable = false;
    private JPanel menu;

    public Player(){
         menu = panel.getMenu();
    }
    
    public void move() {
        clickable = true;
        menu.setOne_step_back(getOne_step_back().setEnable(clickable));

    }
    @Override
    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
        case KeyEvent.VK_UP:
            move();
        }
    }
}

运行报错

  1. 代码行menu.setOne_step_back(getOne_step_back().setEnable(clickable));抛出错误:The method getOne_step_back() is undefined for the type Player.
  2. 替换为menu.getOne_step_back();后抛出错误:The method One_step_back() is undefined for the type JPanel.

错误原因

  • 类型不匹配:Player中声明的menu变量类型为父类JPanel,getOne_step_back()是自定义子类Menu的独有方法,父类类型无法调用子类独有方法
  • 变量未定义:Player构造方法中使用的panel对象没有声明和赋值,属于非法引用
  • 方法调用逻辑错误:
    • 拼写错误:Swing按钮启用状态的设置方法是setEnabled(),不是setEnable()
    • 方法误用:setOne_step_back()是用来替换整个按钮实例的setter方法,不需要在修改按钮状态时调用;且setEnabled()返回值为void,无法作为参数传入setter
    • 作用域错误:getOne_step_back()是Menu类的方法,不能直接在Player类中调用

修改方案

  1. 调整Player类的menu成员变量类型为自定义的Menu,构造方法直接接收Menu实例作为参数,去掉不存在的panel引用
  2. 同步修改MazePanel中成员变量、getter/setter、构造方法的menu类型为Menu,初始化Player时将持有的menu实例传入
  3. 修正move方法中的逻辑:直接通过Menu实例获取按钮对象,调用setEnabled()修改状态即可,不需要调用按钮的setter方法
  4. 修正方法名拼写错误,补全KeyListener接口要求实现的剩余方法

修改后的代码

MazePanel类

public class MazePanel extends JPanel {
    private JFrame frame;
    private Menu menu; // 类型从JPanel改为自定义Menu类
    
    public MazePanel(JFrame frame, Menu menu) {
        this.frame = frame;
        this.menu = menu;
        
        play = new Player(menu); // 初始化Player时传入menu实例
    }

    public Menu getMenu() {
        return menu;
    }

    public void setMenu(Menu menu) {
        this.menu = menu;
    }
}

Main类创建MazePanel的代码无需额外修改,因为传入的本来就是Menu类型实例,参数可自动匹配

Player类

public class Player implements KeyListener{
    boolean clickable = false;
    private Menu menu; // 类型改为自定义Menu类

    // 构造方法接收Menu实例赋值
    public Player(Menu menu){
         this.menu = menu;
    }
    
    public void move() {
        clickable = true;
        // 直接获取按钮实例修改启用状态,修正方法名拼写
        menu.getOne_step_back().setEnabled(clickable);
    }

    @Override
    public void keyPressed(KeyEvent e) {
        switch (e.getKeyCode()) {
        case KeyEvent.VK_UP:
            move();
        }
    }

    // 补全KeyListener接口要求的空实现方法
    @Override
    public void keyTyped(KeyEvent e) {}
    @Override
    public void keyReleased(KeyEvent e) {}
}

修改后即可实现玩家移动后自动启用回退按钮的逻辑,后续实现按钮点击后的禁用逻辑时,只需要在按钮的ActionListener中把按钮设为禁用、同时把clickable置为false即可。


内容的提问来源于stack exchange,提问作者user17159490

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 13:18:21