如果事件不处理,则将事件发送到另一个 NSControl 下的 NSControl
我有多个叠加的控件,可以在某些条件下处理鼠标单击。我想要做的是:
- 顶部控件接收
mouseDown:
事件。 - 顶部控件决定是否处理
mouseDown:
事件。 - 如果是这样,请执行某些操作并阻止其他控件接收
mouseDown:
事件。 - 如果没有,则将事件发送到下面的控件。
- 该控件决定是否处理该事件。
- 本质
上,我试图将事件发送到“Z-Order”位于顶部控件下方的控件,而顶部控件不需要了解其他控件或需要一些特殊的在实例化时设置。
我想到的第一件事是将事件发送到 [topControl nextResponder]
但窗口上所有控件的 nextResponder
似乎是窗口本身,而不是窗口正如我之前所想的,基于 Z 顺序的控件链。
有没有办法做到这一点,而无需手动设置下一个响应者?目标是获得一个独立于其他控件的控件,并且可以将其放在窗口上并按预期工作。
提前致谢!
I have multiple superposed controls which can handle a mouse click under certain conditions. What I want to be able to do is:
- The top control receives the
mouseDown:
event. - The top control decides if it handles the
mouseDown:
event. - If it does, do something and prevent other controls from receiving the
mouseDown:
event. - If it does not, send the event to the control that's underneath.
- This control decides if it handles the event.
- etc.
In essence I'm trying to send the event to the control whose "Z-Order" is just below the top control, without the top control needing to know about the other controls or needing some special setup at instantiation.
The first thing that came to my mind was to send the event to [topControl nextResponder]
but it seems the nextResponder
for all controls on the window is the window itself and not a chain of controls based on their Z-Order as I previously thought.
Is there a way to do this without resorting to setting the next responder manually? The goal is to get a control which is independent from the other controls and can just be dropped on a window and work as expected.
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您所要做的就是调用
[super mouseDown:event]
。从 Mac OS X 10.5 开始(这不以前的工作方式)NSView 知道如何处理重叠视图,并将为您处理事件。如果您需要定位 10.5 之前的版本:这是一个非常糟糕的主意。不仅事件处理机制不知道如何处理重叠的子视图,绘图系统也不知道如何处理,并且您可以看到一些非常奇怪的人工制品。也就是说,如果您确定:
在自定义控件/视图中覆盖
-[NSView hitTest:]
。 AppKit 使用此方法来确定将鼠标事件传递到层次结构中的哪个视图。如果您返回nil
,则自定义视图中的该点将被忽略,并且事件应传递到覆盖该点的下一个视图。但请注意,由于我上面概述的原因,这仍然是一个坏主意。只是当时 AppKit 还没有正式支持它。10.4 及更早版本上更普遍接受的解决方法是使用子窗口。
All you have to do is call
[super mouseDown:event]
. Since Mac OS X 10.5 (this did not work the same way before) NSView knows how to handle overlapping views and will take care of event handling for you.If you need to target releases before 10.5: This is a really bad idea. Not only does the event handling mechanism not know how to deal with overlapping subviews, neither does the drawing system and you can see some very strange artefacts. That said, if you're determined:
Override
-[NSView hitTest:]
in your custom control/view. AppKit uses this method to determine which view in the hierarchy to deliver mouse events to. If you returnnil
that point in your custom view is ignored and the event should get delivered to the next view covering that point.Mind though, this is still a bad idea because of the reasons I outlined above. It just wasn't something formally supported by AppKit at the time. The more generally accepted workaround on 10.4 and earlier is to use a child window.
很难确切地知道最好的方法,因为我不知道您的应用程序是做什么的,但这里有一个想法。听起来您想通过视图层次结构向上传递消息......以某种方式。
无论如何,视图会执行以下两件事之一:
。你会怎么做?视图的默认行为应该是将消息传递到下一个视图。实现这种事情的一个好方法是通过非正式协议。
现在,在应该具有该行为的视图中,您可以执行以下操作:
您可能希望创建一个
NSView
子类来覆盖mouseDown:
,然后您将基于该子类其他自定义视图类。如果您想根据实际的 z 顺序确定“下一个视图”,请记住 z 顺序是由
subviews
集合中的顺序确定的,后面的视图首先出现。所以,你可以这样做:这可能比你想要的要多,但我希望它有帮助。
It's hard to know exactly the best approach because I don't know what your application does, but here's a thought. It sounds like you want to pass the messages up through the view hierarchy... somehow.
Regardless, a view would do one of two things:
So. How would you do this? The default behavior for a view should be to pass the message to the next view. A good way of implementing this kind of thing is through an informal protocol.
Now, in the views that should have that behavior, you'd do this:
You would probably want to create an
NSView
subclass to overridemouseDown:
that you would then base your other custom view classes on.If you wanted to determine the "next view" based on actual z-order, keep in mind that z-order is determined by the order within the
subviews
collection, with later views appearing first. So, you could do something like this:This might be way more than you wanted, but I hope it helps.