NSMenuItem 中的自定义 NSView 未接收鼠标事件
我使用 popUpStatusItemMenu 从 NSStatusItem 中弹出一个 NSMenu。这些 NSMenuItems 显示了一堆不同的链接,每个链接都通过 setAction: 连接到目标的 openLink: 方法。这种安排长期以来一直运作良好。用户从菜单中选择一个链接,然后 openLink: 方法对其进行处理。
不幸的是,我最近决定尝试使用 NSMenuItem 的 setView: 方法来提供更好/更流畅的界面。基本上,我只是停止设置标题,创建 NSMenuItem,然后使用 setView: 显示自定义视图。这工作得很好,菜单项看起来很棒,并且显示了我的自定义视图。
但是,当用户选择菜单项并释放鼠标时,该操作将不再起作用(即不调用 openLink:)。如果我只是简单地注释掉 setView: 调用,那么操作会再次起作用(当然,菜单项是空白的,但操作会正确执行)。那么,我的第一个问题是为什么设置视图会破坏 NSMenuItem 的操作。
没问题,我想,我将通过检测自定义视图中的 mouseUp 事件并从那里调用我的操作方法来修复它。我将此方法添加到我的自定义视图中:
- (void)mouseUp:(NSEvent *)theEvent {
NSLog(@"in mouseUp");
}
没有骰子!这个方法永远不会被调用。
不过,我可以设置跟踪矩形并接收 mouseEntered: 事件。我在 mouseEntered 例程中进行了一些测试,如下所示:
if ([[self window] ignoresMouseEvents]) { NSLog(@"ignoring mouse events"); }
else { NSLog(@"not ignoring mouse events"); }
if ([[self window] canBecomeKeyWindow]) { dNSLog((@"canBecomeKeyWindow")); }
else { NSLog(@"not canBecomeKeyWindow"); }
if ([[self window] isKeyWindow]) { dNSLog((@"isKeyWindow")); }
else { NSLog(@"not isKeyWindow"); }
并得到以下响应:
not ignoring mouse events
canBecomeKeyWindow
not isKeyWindow
这是问题所在吗? “不是isKeyWindow”?大概这不好,因为苹果的文档说“如果用户单击不在关键窗口中的视图,默认情况下该窗口会向前移动并成为关键,但不会调度鼠标事件。”但必须有一种方法可以检测这些事件。如何?
添加:没有任何效果。
[[self window] makeKeyWindow];
尽管 canBecomeKeyWindow 为 YES,但
I have an NSMenu popping out of an NSStatusItem using popUpStatusItemMenu. These NSMenuItems show a bunch of different links, and each one is connected with setAction: to the openLink: method of a target. This arrangement has been working fine for a long time. The user chooses a link from the menu and the openLink: method then deals with it.
Unfortunately, I recently decided to experiment with using NSMenuItem's setView: method to provide a nicer/slicker interface. Basically, I just stopped setting the title, created the NSMenuItem, and then used setView: to display a custom view. This works perfectly, the menu items look great and my custom view is displayed.
However, when the user chooses a menu item and releases the mouse, the action no longer works (i.e., openLink: isn't called). If I just simply comment out the setView: call, then the actions work again (of course, the menu items are blank, but the action is executed properly). My first question, then, is why setting a view breaks the NSMenuItem's action.
No problem, I thought, I'll fix it by detecting the mouseUp event in my custom view and calling my action method from there. I added this method to my custom view:
- (void)mouseUp:(NSEvent *)theEvent {
NSLog(@"in mouseUp");
}
No dice! This method is never called.
I can set tracking rects and receive mouseEntered: events, though. I put a few tests in my mouseEntered routine, as follows:
if ([[self window] ignoresMouseEvents]) { NSLog(@"ignoring mouse events"); }
else { NSLog(@"not ignoring mouse events"); }
if ([[self window] canBecomeKeyWindow]) { dNSLog((@"canBecomeKeyWindow")); }
else { NSLog(@"not canBecomeKeyWindow"); }
if ([[self window] isKeyWindow]) { dNSLog((@"isKeyWindow")); }
else { NSLog(@"not isKeyWindow"); }
And got the following responses:
not ignoring mouse events
canBecomeKeyWindow
not isKeyWindow
Is this the problem? "not isKeyWindow"? Presumably this isn't good because Apple's docs say "If the user clicks a view that isn’t in the key window, by default the window is brought forward and made key, but the mouse event is not dispatched." But there must be a way do detect these events. HOW?
Adding:
[[self window] makeKeyWindow];
has no effect, despite the fact that canBecomeKeyWindow is YES.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
将此方法添加到您的自定义 NSView 中,它将可以很好地处理鼠标事件,
但我在按键处理方面遇到问题,如果您解决了这个问题,也许您可以转到我的问题并帮助我一点。
Add this method to your custom NSView and it will work fine with mouse events
But i'm having problems with keyhandling, if you solved this problem maybe you can go to my question and help me a little bit.
我将此方法添加到我的自定义视图中,现在一切都运行良好:
希望这会有所帮助!
I added this method to my custom view, and now everything works beautifully:
Hope this helps!
将其添加到您的自定义视图中,您应该没问题:
Add this to your custom view and you should be fine:
我已经为
SwiftUI
Swift 5.3
更新了此版本:然后像这样使用:
I've updated this version for
SwiftUI
Swift 5.3
:And then use like so:
到目前为止,实现该目标的唯一方法是在 updateTrackingAreas 中手动注册跟踪区域 - 值得庆幸的是,它被称为,如下所示:
So far, the only way to achieve the goal, is to register a tracking area manually in
updateTrackingAreas
- that is thankfully called, like this:最近,我需要显示 NSStatusItem 的自定义视图,单击它时显示常规 NSMenu,并支持状态图标上的拖放操作。
我主要使用三个不同的来源解决了我的问题,这些来源可以在 这个问题。
希望它能帮助其他人。
Recently I needed to show a Custom view for a NSStatusItem, show a regular NSMenu when clicking on it and supporting drag and drop operations on the Status icon.
I solved my problem using, mainly, three different sources that can be found in this question.
Hope it helps other people.
请参阅 Apple 名为 CustomMenus 的示例代码
在那里您将在 ImagePickerMenuItemView 类中找到一个很好的示例。
让菜单中的视图像普通的 NSMenuItem 一样工作并不简单或微不足道。
有一些真正的决定和编码要做。
See the sample code from Apple named CustomMenus
In there you'll find a good example in the ImagePickerMenuItemView class.
It's not simple or trivial to make a view in a menu act like a normal NSMenuItem.
There are some real decisions and coding to do.