我有一个带有 Swing 用户界面的跨平台 Java 应用程序。在 OS X 上,应用程序使用屏幕菜单栏来获得更原生的用户体验。
通常,应用程序为JFrame
每个文档创建一个。屏幕菜单栏必须在所有这些窗口中保持一致。我尝试了几种方法,发现只有一种一致且高效的解决方案,它足够但并不完美。我发布这个问题以防其他人有更好的方法,并希望这些信息对其他人有所帮助。
一些不起作用的方法:
将相同的菜单栏附加到多个窗口
我尝试将相同的内容添加JMenuBar
到多个JFrame
实例,但Swing 仅支持一次将 JMenuBar 附加到单个 JFrame,即使作为屏幕菜单栏也是如此。
我还使用 AWTMenuBar
而不是 进行了测试JMenuBar
,但发生了同样的现象。并且MenuBar
相比起来有很多限制JMenuBar
(例如,没有图标),所以让我们继续我们想要一个JMenuBar
.
克隆菜单栏
一种常见的解决方案是JMenuBar
为每个新的JFrame
. 然而,这至少存在两个问题。首先,您必须保持菜单栏同步。虽然您可以使用侦听器来执行此操作,但仅处理 OS X 平台就需要很多额外的代码。然而,第二个也是更严重的问题是性能:如果您有一个包含数百个菜单项的复杂菜单栏,那么克隆菜单栏会非常慢。我们发现这种方法将新窗口的出现延迟了几秒钟!
使用默认菜单栏
Apple 的 Java 库中添加了一种新方法,用于OS X v10.6 Update 1 和 10.5 Update 6:.Application.setDefaultMenuBar(JMenuBar)
此方法的既定目的是在 no 处于活动状态时提供菜单栏,但是当没有自己的 noJFrame
处于活动状态时,它也会显示默认菜单栏。JFrame
JMenuBar
但是,该功能存在几个主要问题setDefaultMenuBar
:
- 加速器不起作用。我通过自己处理所有按键来避免我们的应用程序中的这个问题,但这仍然是不幸的。
- 截至 2012 年 12 月,setDefaultMenuBar 在 Java7 上仍然不可用。我们显然希望避免使用已弃用或不受支持的 API。
- 最关键的是,调用
setDefaultMenuBar
会阻止 JVM 正常关闭。即使是随后的调用setDefaultMenuBar(null)
也不会释放必要的资源。
简而言之,setDefaultMenuBar
这似乎根本不是一种安全可靠的方法。
所以,问题是:实现一致屏幕的最可靠、高性能和兼容(跨 OS X 版本)的方法是JMenuBar
什么?