mouseDragged事件被另一个视图窃取

时间:2011-09-17 00:30:39

标签: objective-c cocoa nsview nsresponder

我在另一个MyView中有几个类NSViewNSView的子类)的视图。 MyView实施-mouseEntered:-mouseExited:-mouseDown:-mouseDragged:-mouseUp:

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

有时,MyView会收到鼠标按下事件,但只会在光标保留在MyView内时接收鼠标拖动和鼠标按下事件。如果光标移动到另一个MyView,那么MyView开始接收鼠标拖动的事件(没有先接收鼠标按下事件)并且可以接收后续的鼠标按下事件。

如果重要,鼠标按下事件会在FooView之上创建NSViewMyView的子类),鼠标拖动事件会调整框架的大小。 FooView。这可能是相关的,因为我只能在创建其中一个FooView之后重现问题。 FooView未实现任何鼠标事件方法。

我一直在弄乱这一段时间,并且无法在一个简单的例子中故意重现问题或重新创建问题。我很乐意回答有关我的代码的任何问题,我只是不确定发布的相关部分是什么。

2 个答案:

答案 0 :(得分:2)

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

  1. 在超级视图中,创建一个实例变量,跟踪发生MyView的{​​{1}}实例。
  2. 如果您在-mouseDown:中收到-mouseDragged:,而不是在MyView上操作,请操作存储在超级视图中的self实例引用。
  3. ...然后您将能够始终跟踪正在拖动的对象,而无需运行自己的事件循环。

答案 1 :(得分:0)

您需要在视图中运行自己的鼠标跟踪循环,直到鼠标开启。您可以通过将它们传递给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];
        }
    }
}