mouseDragged 事件被另一个视图窃取

发布于 2024-12-05 04:53:35 字数 864 浏览 0 评论 0原文

我在另一个 NSView 中有几个类 MyViewNSView 的子类)的视图。 MyView 实现 -mouseEntered:-mouseExited:-mouseDown:-mouseDragged:和<代码>-mouseUp:。

几乎总是,当 MyView 接收到鼠标按下事件时,所有后续的鼠标拖动事件都会由同一 MyView 接收,直到下一个鼠标松开事件。即使光标超出了MyView。这是预期的行为。

有时,MyView 会接收鼠标按下事件,但只会在光标保留在 MyView 内时接收鼠标拖动和鼠标向上事件。如果光标移动到另一个 MyView 上,则该 MyView 开始接收鼠标拖动事件(无需首先接收鼠标按下事件),并且可以接收后续的鼠标松开事件事件。

如果重要的话,鼠标按下事件会在 MyView 顶部创建一个 FooViewNSView 的子类),并且鼠标拖动事件调整 FooView 的框架大小。这可能是相关的,因为我只能在创建这些 FooView 之一后才能重现该问题。 FooView 不实现任何鼠标事件方法。

我已经搞乱这个问题有一段时间了,但无法故意重现该问题或在一个简单的示例中重新创建该问题。我很乐意回答有关我的代码的任何问题,我只是不确定要发布的相关部分是什么。

I have several views of class MyView (subclass of NSView) inside another NSView. MyView implements -mouseEntered:, -mouseExited:, -mouseDown:, -mouseDragged:, and -mouseUp:.

Almost always, when a MyView receives a mouse-down event, all subsequent mouse-dragged events are received by the same MyView until the next mouse-up event. Even if the cursor goes outside of the MyView. That is the expected behavior.

Occasionally, a MyView will receive a mouse-down event, but will only receive mouse-dragged and mouse-up events while the cursor remains inside the MyView. If the cursor moves onto a different MyView, then that MyView starts receiving mouse-dragged events (without first receiving a mouse-down event) and can receive the subsequent mouse-up event.

In case it matters, the mouse-down event creates a FooView (subclass of NSView) on top of the MyView, and the mouse-dragged events resize the frame of the FooView. This might be related, as I've only been able to reproduce the problem after one of these FooViews has been created. FooView does not implement any of the mouse event methods.

I've been messing with this for a while now and haven't been able to either purposely reproduce the problem or recreate the problem in a simple example. I'd be happy to answer any questions about my code, I'm just not sure what would be the relevant part to post.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

静待花开 2024-12-12 04:53:35

不确定根本问题是什么(这种 Cocoa 行为对我来说似乎不一致)...但这里有一个可能的解决方法:

  1. 在超级视图中,创建一个实例变量来跟踪 MyView 实例,其中 -mouseDown:发生了。
  2. 当您在 MyView 中收到 -mouseDragged: 时,不要对 self 进行操作,而是对 MyView 实例引用进行操作存储在超级视图中。

...然后您将能够持续跟踪正在拖动的对象,而无需运行自己的事件循环。

Not sure what the root issue is (this Cocoa behavior seems inconsistent to me)... but here's one possible workaround:

  1. In the superview, create an instance variable tracking the MyView instance in which the -mouseDown: occurred.
  2. When you receive a -mouseDragged: in MyView, instead of operating on self, operate on the MyView instance reference stored in the superview.

...then you'll be able to consistently track which object is being dragged, without having to run your own event loop.

迷迭香的记忆 2024-12-12 04:53:35

您需要在视图中运行自己的鼠标跟踪循环,直到鼠标抬起。您可以通过将事件传递到 nextEventMatchingMask: 来扩展它以处理更多类型的事件。

- (void)mouseDown:(NSEvent*)event
{
    CGPoint hitPoint = [self pointInViewSpaceFromEvent:event];

    BOOL isDragging = NO;
    BOOL isTracking = YES;

    while (isTracking)
    {       
        switch ([event type])
        {
            case NSLeftMouseDown:
                [self singleMouseDownAtPoint:hitPoint withModifierFlags:[event modifierFlags]];
                break;

            case NSLeftMouseUp:
                isTracking = NO;
                if (isDragging)
                    [self mouseDraggingDidEndAtPoint:hitPoint];
                else
                    [self singleMouseUpAtPoint:hitPoint withEvent:event];
                break;

            case NSLeftMouseDragged:
                if (isDragging)
                    [self mouseDraggingAtPoint:hitPoint withModifierFlags:[event modifierFlags]];
                else
                    isDragging = YES;
                break;
            default:
                break;
        }

        if (isTracking)
        {
            event = [[self window] nextEventMatchingMask:NSLeftMouseDraggedMask | NSLeftMouseUpMask];
            hitPoint = [self pointInViewSpaceFromEvent:event];
        }
    }
}

You need to run you own mouse tracking loop in the view until mouse is up. You can extend it to process more types of events by passing them into nextEventMatchingMask:.

- (void)mouseDown:(NSEvent*)event
{
    CGPoint hitPoint = [self pointInViewSpaceFromEvent:event];

    BOOL isDragging = NO;
    BOOL isTracking = YES;

    while (isTracking)
    {       
        switch ([event type])
        {
            case NSLeftMouseDown:
                [self singleMouseDownAtPoint:hitPoint withModifierFlags:[event modifierFlags]];
                break;

            case NSLeftMouseUp:
                isTracking = NO;
                if (isDragging)
                    [self mouseDraggingDidEndAtPoint:hitPoint];
                else
                    [self singleMouseUpAtPoint:hitPoint withEvent:event];
                break;

            case NSLeftMouseDragged:
                if (isDragging)
                    [self mouseDraggingAtPoint:hitPoint withModifierFlags:[event modifierFlags]];
                else
                    isDragging = YES;
                break;
            default:
                break;
        }

        if (isTracking)
        {
            event = [[self window] nextEventMatchingMask:NSLeftMouseDraggedMask | NSLeftMouseUpMask];
            hitPoint = [self pointInViewSpaceFromEvent:event];
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文