我有一个跨平台的Java应用程序,具有Swing用户界面。在OS X上,该应用程序使用屏幕菜单栏以获得更本地化的用户体验。
一般情况下,该应用程序为每个文档创建一个
一些行不通的方法:
我还尝试过使用AWT的MenuBar而不是JMenuBar,但是出现了相同的现象。与JMenuBar相比,MenuBar有许多限制(例如没有图标),因此让我们继续满足需要一个JMenuBar的要求。
克隆菜单栏 一种常见的解决方案是为每个新的JFrame创建一个JMenuBar的副本。然而,这种方法至少存在两个问题。首先,您必须保持菜单栏同步。虽然可以使用监听器来完成,但这是处理OS X平台所需的大量额外代码。但是,第二个更严重的问题是性能:如果您有一个具有数百个菜单项的复杂菜单栏,则克隆菜单栏非常慢。我们发现这种方法会使新窗口的出现延迟数秒!
使用默认菜单栏
一般情况下,该应用程序为每个文档创建一个
JFrame
。屏幕菜单栏必须在所有这些窗口中保持一致。我尝试了几种方法,发现只有一种一致且高效的解决方案,虽然不完美但已足够。我发布这个问题是希望其他人有更好的方法,并希望这些信息能帮助其他人。一些行不通的方法:
将相同的菜单栏附加到多个窗口
我尝试将相同的JMenuBar
添加到多个JFrame
实例,但Swing仅支持将JMenuBar附加到单个JFrame中, 即使作为屏幕菜单栏也是如此。我还尝试过使用AWT的MenuBar而不是JMenuBar,但是出现了相同的现象。与JMenuBar相比,MenuBar有许多限制(例如没有图标),因此让我们继续满足需要一个JMenuBar的要求。
克隆菜单栏 一种常见的解决方案是为每个新的JFrame创建一个JMenuBar的副本。然而,这种方法至少存在两个问题。首先,您必须保持菜单栏同步。虽然可以使用监听器来完成,但这是处理OS X平台所需的大量额外代码。但是,第二个更严重的问题是性能:如果您有一个具有数百个菜单项的复杂菜单栏,则克隆菜单栏非常慢。我们发现这种方法会使新窗口的出现延迟数秒!
使用默认菜单栏
苹果的Java库中添加了一个新的方法Java for OS X v10.6 Update 1 and 10.5 Update 6:Application.setDefaultMenuBar(JMenuBar)
。
该方法的目的是在没有活动的JFrame
时提供菜单栏,但当一个没有自己的JMenuBar
的JFrame
处于活动状态时,它也会显示默认的菜单栏。
然而,setDefaultMenuBar
功能存在几个主要问题:
- 加速键无法使用。我们在应用程序中通过自己处理所有按键操作来避免这个问题,但这仍然很不幸。
- 截至2012年12月,setDefaultMenuBar仍然不可用于Java7。我们显然要避免使用已弃用或不受支持的API。
- 最关键的是,调用
setDefaultMenuBar
会阻止JVM正常关闭。即使随后调用setDefaultMenuBar(null)
也不能释放必要的资源。
简而言之,setDefaultMenuBar
似乎并不是一个安全且健壮的选择。
JFrame
制作一个新副本会产生实质性的内存和时间开销。如上所述,在树中大约有500个菜单项时,新JFrame
的外观会被延迟数秒!至于同步问题,如果您的菜单结构发生更改,则会有影响:A)添加新菜单项;B)删除菜单项;C)重命名菜单项;D)使用JCheckBoxMenuItem
或JRadioButtonMenuItem
,因为这些具有关联状态,可能需要在不同的JFrame
之间保持同步。 - ctruedensetDefaultMenuBar
了吗?你有相关问题或文章的链接吗? - ctrueden