鼠标在部分隐藏的NSView上进入/退出事件

cls*_*oud 5 macos mouse cocoa objective-c nsview

我有一个问题,我认为可以解决一些hackery,但我很好奇,如果有一个更简单的方法来完成工作,而不必做所有这些.

我有一堆NSView(层支持,如果它以某种方式帮助提供一些更好的解决方案),如下所示:

视图堆栈/布局

这里的事情是,它本质上是一个菜单,但是悬停敏感.如果用户将鼠标悬停在较低级别视图的某个公开部分上,我需要根据视图的内容执行操作.它是一个动态系统,因此像这样堆叠的菜单项的数量可能会改变,使静态计算更加困难.正如您所看到的,它们基本上都是第一个项目的副本(形状方面),但随后通过简单的变换旋转进一步向下旋转.

我对SO社区的问题是你们都认为获得mouseEntered的最佳方法是什么:和mouseExited:只针对这些视图的字面可见部分的事件?

我试图做的是在这些视图的visibleRect部分使用NSTrackingArea,这听起来比在这种情况下更实用.实际上,visibleRect似乎始终对所有这些人都是"可见的".除了部分重叠的NSView之外,没有任何东西被明确阻止或隐藏.所有这一切都是我从所有视图中得到一个垃圾邮件控制台,一旦鼠标进入他们的矩形就会尖叫.

我正在考虑的是制作每个菜单项的子NSView,并让每个菜单项负责跟踪区域......每个菜单项都有可以报告的右侧和底侧的"条带"视图,但这仍然是一点点黑客,是icky.

有没有人有更好的主意?也许是经验之一?

谢谢!

rde*_*mar 3

我知道您已经有了一个解决方案,但我想我会尝试一种不同的方法,不需要获取大量的 mouseMoved 事件。我在代码中创建了 3 个自定义视图,为它们添加了跟踪矩形,并将所有 mouseEntered 和 mouseExited 消息发送到执行 hitTest 以确定哪个视图最顶层的相同方法。这是窗口内容视图的代码。

@implementation MainView
@synthesize oldView;

-(void)awakeFromNib {
    oldView = nil;
    Card *card1 = [[Card alloc]initWithFrame:NSMakeRect(150, 150, 200, 150) color:[NSColor redColor] name:@"Red Box"];
    NSTrackingArea *area1 = [[NSTrackingArea alloc]initWithRect:card1.frame options:NSTrackingMouseEnteredAndExited|NSTrackingActiveInActiveApp owner:self userInfo:nil];
    [self addTrackingArea:area1];
    [self addSubview:card1];

    Card *card2 = [[Card alloc]initWithFrame:NSMakeRect(180, 120, 200, 150) color:[NSColor yellowColor] name:@"Yellow Box"];
    NSTrackingArea *area2 = [[NSTrackingArea alloc]initWithRect:card2.frame options:NSTrackingMouseEnteredAndExited|NSTrackingActiveInActiveApp owner:self userInfo:nil];
    [self addTrackingArea:area2];
    [self addSubview:card2];

    Card *card3 = [[Card alloc]initWithFrame:NSMakeRect(210, 90, 200, 150) color:[NSColor greenColor] name:@"Green Box"];
    NSTrackingArea *area3 = [[NSTrackingArea alloc]initWithRect:card3.frame options:NSTrackingMouseEnteredAndExited|NSTrackingActiveInActiveApp owner:self userInfo:nil];
    [self addTrackingArea:area3];
    [self addSubview:card3];
}

-(void)mouseEntered:(NSEvent *)theEvent {
    [self reportTopView:theEvent];
}

-(void)mouseExited:(NSEvent *)theEvent {
    [self reportTopView:theEvent];
}

-(void)reportTopView:(NSEvent *)theEvent {
    id topView = [self hitTest:[theEvent locationInWindow]];
    if (![topView isEqual:oldView]) {
        oldView = topView;
        ([topView isKindOfClass:[Card class]])? NSLog(@"%@",[(Card *)topView name]):NULL;
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我所说的卡片(彩色矩形)的代码:

@implementation Card
@synthesize name,fillColor;

- (id)initWithFrame:(NSRect)frame color:(NSColor *)color name:(NSString *)aName{
    self = [super initWithFrame:frame];
    if (self) {
        self.fillColor = color;
        self.name = aName;
    }
    return self;
}

- (void)drawRect:(NSRect)rect {
    [self.fillColor drawSwatchInRect:rect];

}
Run Code Online (Sandbox Code Playgroud)

  • @jp.rider63,是的,那是因为我正在使用 ARC。 (2认同)