如何解决如何创建一个包含 NSMenuItem 的 NSMenu,该 NSMenuItem 仅在按住键盘修饰键时出现?
我想创建一个 NSMenu
,其中包含一个默认隐藏的 NSMenuItem
,并且仅在用户按住键盘修改键时才会出现。
基本上,我正在寻找与 Finder 的“Go”菜单中的“Library”选项相同的行为:
我已经尝试使用 [NSEvent addGlobalMonitorForEventsMatchingMask: handler:]
安装密钥侦听器,通过设置 NSMenuItem
属性以编程方式隐藏和取消隐藏 hidden
。这种方法有效,但问题是当 NSMenu
打开时隐藏/取消隐藏不起作用。显然,NSMenu
在打开时完全接管了事件处理循环,从而阻止了键侦听器的工作。
我可能可以使用 CGEventTap 在 NSMenu
打开时仍然接收事件,但这似乎完全是矫枉过正。
我发现的另一个与我想要的类似的东西是 NSMenu
的“alternate”机制。但我只能让它切换 NSMenuItems
,而不是隐藏/取消隐藏它们。
任何帮助将不胜感激。谢谢!
解决方法
假设您的仅选项菜单项的操作是(在 Swift 中)performOptionOnlyMenuItem(_:)
,其目标是您的 AppDelegate
。
-
您需要做的第一件事是确保
AppDelegate
符合NSMenuItemValidation
协议。 -
您需要做的第二件事是实现
validateMenuItem(_:)
方法,并让它检查菜单项是否发送performOptionOnlyMenuItem(_:)
操作。如果是,则根据当前是否按下选项键来设置项目的isHidden
属性。
如果您不需要验证任何其他菜单项,代码可以如下所示:
extension AppDelegate: NSMenuItemValidation {
func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
switch menuItem.action {
case #selector(performOptionOnlyMenuItem(_:)):
let flags = NSApp.currentEvent?.modifierFlags ?? []
menuItem.isHidden = !flags.contains(.option)
return true
default:
return true
}
}
}
如果操作被发送到某个其他目标,您需要在该目标上实施验证(包括协议一致性)。每个菜单项仅由项的目标验证。
,我找到了一个完美的解决方案!
-
在您想要隐藏的
NSMenuItem
上,将alternate
属性设置为YES
,并将keyEquivalentModifierMask
属性设置为您想要取消隐藏该项目。 -
在您的
NSMenu
中,就在要隐藏的NSMenuItem
之前,插入另一个高度为 0 的NSMenuItem
。 >在 Objc 中,您可以像这样创建一个高度为 0 的
NSMenuItem
:NSMenuItem *i = [[NSMenuItem alloc] init]; i.view = [[NSView alloc] initWithFrame:NSZeroRect];
可隐藏的 NSMenuItem
现在将“替代”它前面的零高度 NSMenuItem
。默认情况下将显示零高度项目,但是当您按住您指定的键盘修饰符时,零高度项目将与可隐藏项目换出。由于零高度项是不可见的,因此具有取消隐藏可隐藏项的效果。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。