cursorUpdate被调用,但游标未更新

时间:2013-03-16 16:44:33

标签: cocoa cursor nstextview nscursor

我一直在研究这个问题几个小时,不知道出了什么问题。我想要一个按钮的自定义光标,它是NSTextView的子视图,我添加了一个跟踪区域,并在鼠标输入按钮时发送cursorUpdate消息。

每次鼠标进入跟踪区域时,都会调用cursorUpdate方法。但光标仍然是IBeamCursor。

有什么想法吗?

Apple Docs的参考:managing cursor-update event

- (void)cursorUpdate:(NSEvent *)event {
    [[NSCursor arrowCursor] set];
}

- (void)myAddTrackingArea {
    [self myRemoveTrackingArea];

    NSTrackingAreaOptions trackingOptions = NSTrackingCursorUpdate | NSTrackingMouseEnteredAndExited | NSTrackingActiveInKeyWindow;
    _trackingArea = [[NSTrackingArea alloc] initWithRect: [self bounds] options: trackingOptions owner: self userInfo: nil];
    [self addTrackingArea: _trackingArea];
}

- (void)myRemoveTrackingArea {
    if (_trackingArea)
    {
        [self removeTrackingArea: _trackingArea];
        _trackingArea = nil;
    }
}

3 个答案:

答案 0 :(得分:4)

我遇到了同样的问题。

问题是,NSTextView每次收到mouseMoved:事件时都会更新其光标。该事件由NSTrackingArea的自我更新NSTextView触发,该NSTextView始终跟踪NSScrollViewupdateTrackingAreas的可见部分。所以我可以想到两种解决方案。

  1. 覆盖mouseMoved:删除Cocoa提供的跟踪区域,并确保始终创建一个新的跟踪区域,而不是按钮。 (我不会这样做!)

  2. 覆盖- (void)mouseMoved:(NSEvent *)theEvent { NSPoint windowPt = [theEvent locationInWindow]; NSPoint superViewPt = [[self superview] convertPoint: windowPt fromView: nil]; if ([self hitTest: superViewPt] == self) { [super mouseMoved:theEvent]; } } 并确保当光标位于按钮上时它不会调用super。

    {{1}}

答案 1 :(得分:0)

我刚刚通过谷歌搜索遇到了这个问题,所以我想我会发布我的解决方案。

  1. NSTextView / NSTextField的子类。
  2. 按照文档to create an NSTrackingArea中的步骤操作。应该看起来像下面这样。将此代码放在子类的init方法中(也添加updateTrackingAreas方法):

    NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingMouseMoved | NSTrackingActiveInKeyWindow) owner:self userInfo:nil];
    [self addTrackingArea:trackingArea];
    self.trackingArea = trackingArea;
    
  3. 现在您需要将mouseMoved:方法添加到子类:

    - (void)mouseMoved:(NSEvent *)theEvent {
        NSPoint point = [self convertPoint:theEvent.locationInWindow fromView:nil];
        if (NSPointInRect(point, self.popUpButton.frame)) {
            [[NSCursor arrowCursor] set];
        } else {
            [[NSCursor IBeamCursor] set];
        }
    }
    
  4. 注意:self.popUpButton是按钮,它是NSTextView / NSTextField的子视图。

    就是这样!结果不是太难 - 只需使用mouseMoved:代替cursorUpdate:。我花了几个小时来解决这个问题,希望有人可以使用它。

答案 2 :(得分:0)

我遇到了同样的问题,但是使用了一个简单的NSView子类,该子类是窗口的contentView的子类,并且没有驻留在NScrollView内。

cursorUpdate的{​​{1}}标志的文档听起来像您只需要处理进入跟踪区域rect的鼠标即可。但是,我必须手动检查鼠标的位置,因为当鼠标进入跟踪区域的矩形和离开跟踪矩形的时都会调用NSTrackingArea方法。因此,如果cursorUpdate(event:)实现仅设置光标而不检查其是否位于跟踪区域rect内,则在进入并离开 rect时都将对其进行设置。

cursorUpdate(event:)的文档说明:

重写此方法以设置光标图像。默认值 如果使用游标矩形,则实现使用游标矩形 目前有效。如果不是,则调用super发送消息 响应者链上。

如果响应者实现了此方法,但决定不处理 特定事件,它应调用的超类实现 这种方法

cursorUpdate(event:)