如何避免MenuListener::menuSelected创建的Frame被主Frame遮挡?
这个问题我之前也碰到过,核心原因是**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
相关产品推荐
相关产品推荐

