2

我有一个仅状态栏项目的应用程序,我试图在 mouseOver 上显示一个面板。我已经连接并工作了自定义状态项(和相关视图),但跟踪矩形仅在每十几个启动时接收事件。这使我相信某处发生了竞争情况,但我找不到。在我的自定义状态栏项目视图中:

- (id)initWithStatusItem:(NSStatusItem *)statusItem {
    CGFloat itemWidth = [statusItem length];
    CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
    NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
    NSLog(@"itemRect: %@", NSStringFromRect(itemRect));

    if ((self = [super initWithFrame:itemRect])) {
        _statusItem = statusItem;
        _statusItem.view = self;

        NSTrackingAreaOptions options = NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingActiveAlways;
        NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:itemRect
                                                                    options:options
                                                                      owner:self
                                                                   userInfo:nil];
        [self addTrackingArea:trackingArea];

        [self.window setIgnoresMouseEvents:NO];
        [self.window setAcceptsMouseMovedEvents:YES];

        self.wantsLayer = YES;
    }
    return self;
}

- (void)mouseEntered:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:UAStatusItemMouseEnteredNotification object:nil];
}

- (void)mouseExited:(NSEvent *)theEvent {
    [[NSNotificationCenter defaultCenter] postNotificationName:UAStatusItemMouseExitedNotification object:nil];
}

在大多数启动时,应用程序不会响应跟踪鼠标事件,但每隔一段时间,mouseEntered:mouseExited:方法就会被正确调用,这让我完全困惑。这里发生了什么,我做错了什么?




编辑 07/17/2012
我根据@Streams 的回答更改了代码,但看到了同样的问题:

- (id)initWithStatusItem:(NSStatusItem *)statusItem {
    CGFloat itemWidth = [statusItem length];
    CGFloat itemHeight = [[NSStatusBar systemStatusBar] thickness];
    NSRect itemRect = NSMakeRect(0.0, 0.0, itemWidth, itemHeight);
    NSLog(@"itemRect: %@", NSStringFromRect(itemRect));

    if ((self = [super initWithFrame:itemRect])) {
        _statusItem = statusItem;
        _statusItem.view = self;            

        [self updateTrackingAreas];

        [self.window setIgnoresMouseEvents:NO];
        [self.window setAcceptsMouseMovedEvents:YES];

        self.wantsLayer = YES;
    }
    return self;
}

- (void)updateTrackingAreas {

    if (self.trackingArea)
        [self removeTrackingArea:self.trackingArea];

    [super updateTrackingAreas];

    self.trackingArea = [[NSTrackingArea alloc] initWithRect:CGRectZero
                                                     options:NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingInVisibleRect | NSTrackingActiveAlways
                                                       owner:self
                                                    userInfo:nil];
    [self addTrackingArea:self.trackingArea];
}




编辑 07/18/2012
这是一个准系统示例项目,它使用众所周知的 github 项目(由 @Stream 编写)来显示问题。它不能可靠地接收鼠标悬停事件,如果有的话。

4

2 回答 2

3

我打开了一个 DTS 请求让 Apple 看看这个。这是回应:

...启动应用程序时,您在 Xcode 中使用全屏。我[之前]没有这样做,但我现在可以重现这个问题。据我所知,只有当您的应用程序在 Xcode 中从全屏模式启动时才会发生。您的用户不会以这种方式启动应用程序。这是 AppKit 的全屏模式的问题,不一定是您的代码。

于 2012-07-23T22:35:01.927 回答
0

我相信你应该只在-[NSView updateTrackingAreas]. 例如:

- (void)updateTrackingAreas
{
    if (_trackingArea) {
        [self removeTrackingArea:_trackingArea];
    }

    [super updateTrackingAreas];

    NSTrackingAreaOptions options = (NSTrackingMouseEnteredAndExited |
                                     NSTrackingMouseMoved |
                                     NSTrackingInVisibleRect |
                                     NSTrackingActiveAlways);
    _trackingArea = [[NSTrackingArea alloc] initWithRect:CGRectZero
                                                 options:options
                                                   owner:self
                                                userInfo:nil];
    [self addTrackingArea:_trackingArea];
}
于 2012-07-17T22:18:53.717 回答