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); } }
Menu面板类
按钮在构造方法中创建并初始化为禁用,同时编写了对应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(); } } }
运行报错
- 代码行
menu.setOne_step_back(getOne_step_back().setEnable(clickable));抛出错误:The method getOne_step_back() is undefined for the type Player. - 替换为
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类中调用
- 拼写错误:Swing按钮启用状态的设置方法是
修改方案
- 调整Player类的menu成员变量类型为自定义的
Menu,构造方法直接接收Menu实例作为参数,去掉不存在的panel引用 - 同步修改MazePanel中成员变量、getter/setter、构造方法的menu类型为
Menu,初始化Player时将持有的menu实例传入 - 修正move方法中的逻辑:直接通过Menu实例获取按钮对象,调用
setEnabled()修改状态即可,不需要调用按钮的setter方法 - 修正方法名拼写错误,补全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
相关产品推荐
相关产品推荐

