Cocoa 拖动时嵌套视图上未调用NSView mouseEntered-黑客攻击是唯一选项吗?

Cocoa 拖动时嵌套视图上未调用NSView mouseEntered-黑客攻击是唯一选项吗?,cocoa,mouseevent,drag,nsview,Cocoa,Mouseevent,Drag,Nsview,我有一个带有嵌套NSView的NSView,如果我不拖动鼠标,则使用NSTracking area在所有子视图上触发事件…很好 但当我从父NSView拖动到子NSView上时,鼠标事件不会被触发,然后我让它们响应事件的唯一方法是通过黑客攻击,这感觉很脏 NSView *hit = [self findViewUnderPoint:loc]; if (hit != nil) { if (hit != last) { [last mouseExited:event];

我有一个带有嵌套NSView的NSView,如果我不拖动鼠标,则使用NSTracking area在所有子视图上触发事件…很好

但当我从父NSView拖动到子NSView上时,鼠标事件不会被触发,然后我让它们响应事件的唯一方法是通过黑客攻击,这感觉很脏

NSView *hit = [self findViewUnderPoint:loc];
if (hit != nil)
{
    if (hit != last)
    {
        [last mouseExited:event]; // This looks terrible to me
    } else {
        [hit mouseEntered:event]; // This looks terrible to me
    }
    last = hit;
}
如果你注释掉上面的代码,子视图事件不会被触发,如果你把它留在里面,它们是…但是我直接调用它们

我已经上传了一段视频,向您展示了它是如何工作的,然后是拖动(通过我的hacks)——我还包括了我的源代码

理想情况下,我追求的是“正确的方式”


问题可能与子类化的方式有关。 是否在重写的类方法中调用超级方法? 您是对特定的预先存在的控件进行子分类,还是立即从NSView中删除? 你在XCode中得到任何警告吗

编辑:

嗨, 我在玩一个像你这样简单的东西

您是否查看了CableView子类中的hitTest:override?也许它应该以不同的方式返回: 返回self==hitView?自我:无

这是我对视图子类的愚蠢实现,它在拖动时绘制一个指南:

#import "MYSimpleScratchPad.h"

@implementation MYSimpleScratchPad
{
    NSPoint start;
    NSPoint finish;
    BOOL dragging;
}

- (instancetype)initWithFrame:(NSRect)frameRect {
    self = [super initWithFrame:frameRect];
    if (self) {
        _path = [NSBezierPath bezierPath];
        dragging = NO;
    }
    return self;
}

- (void)drawRect:(NSRect)dirtyRect {
    [super drawRect:dirtyRect];

    [[NSColor redColor] set];
    [_path removeAllPoints];
    if (dragging) {
        [_path setLineWidth:5.0];
        [_path setLineCapStyle:NSRoundLineCapStyle];
        [_path moveToPoint:start];
        [_path lineToPoint:finish];
        [_path stroke];
    }

}

- (void)mouseDown:(NSEvent *)event {
    start = [event locationInWindow];
    NSRect theFrame = [self frame];
    start.x -= theFrame.origin.x;
    start.y -= theFrame.origin.y;
    _path = [NSBezierPath bezierPath];
}

- (void)mouseDragged:(NSEvent *)event {
    finish = [event locationInWindow];
    NSRect theFrame = [self frame];
    finish.x -= theFrame.origin.x;
    finish.y -= theFrame.origin.y;
    dragging = YES;
    [self setNeedsDisplay:YES];
}

- (void)mouseUp:(NSEvent *)event {
    start = NSMakePoint(0.0, 0.0);
    finish = NSMakePoint(0.0, 0.0);
    dragging = NO;
    [self setNeedsDisplay:YES];
}

- (NSView *)hitTest:(NSPoint)point {
    NSView *hitView = [super hitTest:point];
    return self == hitView ? self:nil;
}

@end

如中所述,有两种方法可以实现拖动。您的解决方案使应用程序的正常事件循环短路,您必须调用
mouseenterned:
mouseExited:
。如果您不想这样做,请实施三种方法方法,这还有其他缺点。

您使用的是NSTrackingEnabledDuringMouseDrag吗?顺便说一句,您的dropbox.com链接对我不起作用。@Ssswift-是的,NSTrackingEnabledDuringMouseDrag已启用。您好,Xcode中没有关于该问题的警告,我正在直接对NSView进行子类化,也没有调用super,你能看到dropbox项目吗?嗨,可能问题与你的一些视图没有传播到下一个响应者mouseDown:事件有关。您是否尝试过在重写方法的逻辑中的某些点调用[super mouseDown:event]?您能否解释一下三种方法的缺点?“然而,这种技术可能需要更多的代码和实例变量。”。示例代码演示了这两种方法。