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

如何避免MenuListener::menuSelected创建的Frame被主Frame遮挡?

解决MenuListener创建的窗口被主窗口遮挡的问题

这个问题我之前也碰到过,核心原因是**menuSelected事件触发的时机不对**:当你点击menuB触发menuSelected时,菜单还处于展开激活的状态,Swing的事件队列里还有一堆和菜单显示相关的任务等着处理。这时候直接创建新窗口,新窗口的层级和焦点会被主窗口(还有正在显示的菜单)干扰,导致它被压在下面。而ActionListener触发时,菜单已经完成关闭流程,事件队列处于正常状态,所以新窗口能正常显示。

最简单也最符合Swing规范的解决方法是把创建窗口的代码放到SwingUtilities.invokeLater()里,让它在当前所有事件(包括菜单的关闭处理)完成后再执行:

@Override
public void menuSelected(MenuEvent e) {
    Object source = e.getSource();
    if(source == menuB) {
        // 把窗口创建逻辑放到事件队列末尾
        SwingUtilities.invokeLater(() -> new MyFrame("Three"));
    }
}

如果你不想修改MenuListener的代码,也可以在MyFrame的构造方法最后加上两行,强制让窗口前置并获取焦点:

MyFrame(String title) {
    frame = new JFrame(title);
    initComponents(frame);
    frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    frame.setSize(new Dimension(WIDTH, HEIGHT));
    frame.setLocation(((Toolkit.getDefaultToolkit().getScreenSize().width - frame.getSize().width) / 2), ((Toolkit.getDefaultToolkit().getScreenSize().height - frame.getSize().height) / 2));
    frame.setResizable(false);
    frame.setVisible(true);
    // 强制前置并获取焦点
    frame.toFront();
    frame.requestFocus();
}

不过第一种方法更推荐,因为它遵循了Swing的单线程模型,避免了潜在的UI线程冲突问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:09:21