使用CardLayout的JFrame面板切换后关闭异常问题咨询
问题原因
你遇到的问题核心在于JFrame默认关闭操作未被正确拦截:
- JFrame默认的
defaultCloseOperation是HIDE_ON_CLOSE,当点击关闭按钮时,即便你在windowClosing回调里切换回SettingsPanel,后续默认的窗口隐藏操作依然会执行,导致SettingsPanel刚显示就被隐藏,进程因未触发退出逻辑而保持活跃。 - 你在
windowClosing方法中调用的super.windowClosing(e);无实际作用(父类方法为空实现),但关键是没有阻止JFrame执行默认的关闭行为。
解决方案
- 在JMate构造函数中添加
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);,禁用默认关闭操作,完全由自定义逻辑处理关闭事件。 - 移除
windowClosing方法中的super.windowClosing(e);(无实际意义)。
修改后的核心代码
public JMate(){ setTitle("JMate v1.0.0"); setLocationRelativeTo(null); setResizable(false); // 禁用默认关闭操作,交由自定义逻辑处理 setDefaultCloseOperation(DO_NOTHING_ON_CLOSE); container = new JPanel(); settingsPanel = new SettingsPanel(this); playingPanel = new PlayingPanel(this); cardLayout = new CardLayout(); container.setLayout(cardLayout); container.add(settingsPanel, settingsPanel.getClass().getName()); container.add(playingPanel, playingPanel.getClass().getName()); cardLayout.show(container, settingsPanel.getClass().getName()); activePanel = settingsPanel; add(container); setSize(settingsPanel.getPreferredSize()); addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { if(activePanel == settingsPanel){ System.exit(0); } else{ cardLayout.show(container, settingsPanel.getClass().getName()); setSize(settingsPanel.getPreferredSize()); activePanel = settingsPanel; //TODO: stop engine etc. } } }); setVisible(true); }
额外优化建议
- 避免用
setSize硬设窗口大小,推荐调用pack()让窗口自动适配面板首选尺寸,更符合Swing布局规范。 - 将面板标识字符串(如
settingsPanel.getClass().getName())替换为常量,避免类名变化引发错误,提升代码可读性。
内容的提问来源于stack exchange,提问作者smilly
相关产品推荐
相关产品推荐

