我已经为此工作了几个小时,不知道出了什么问题。我想要一个按钮的自定义光标,该按钮是NSTextView的子视图,我添加一个跟踪区域并在鼠标输入按钮时发送光标更新消息。
每次鼠标进入跟踪区域时,确实会调用 cursorUpdate 方法。但光标仍然是IBeamCursor。
有什么想法吗?
Apple 文档参考:管理光标更新事件
- (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;
}
}
我遇到了同样的问题。
问题是,NSTextView
每次收到mouseMoved:
事件时都会更新其光标。该事件由NSTextView
的自我更新NSTrackingArea
触发,该总是跟踪NSScrollView
内NSTextView
的可见部分。所以我能想到的可能有两种解决方案。
-
覆盖
updateTrackingAreas
删除 Cocoa 提供的跟踪区域,并确保始终创建一个排除按钮的新区域。(我不会这样做! -
覆盖
mouseMoved:
并确保当光标位于按钮上时它不会调用 super。- (void)mouseMoved:(NSEvent *)theEvent { NSPoint windowPt = [theEvent locationInWindow]; NSPoint superViewPt = [[self superview] convertPoint: windowPt fromView: nil]; if ([self hitTest: superViewPt] == self) { [super mouseMoved:theEvent]; } }
我遇到了同样的问题,但使用了一个简单的NSView
子类,它是窗口contentView
的子类,并且不驻留在NScrollView
内。
NSTrackingArea
的cursorUpdate
标志的文档听起来像您只需要处理鼠标进入跟踪区域即可。但是,我必须手动检查鼠标位置,因为当鼠标进入跟踪区域的矩形和离开跟踪矩形时都会调用cursorUpdate(event:)
方法。因此,如果cursorUpdate(event:)
实现只设置光标而不检查它是否位于跟踪区域矩形内,则在它进入和离开矩形时都会设置它。
cursorUpdate(event:)
的文档指出:
重写此方法以设置光标图像。默认如果游标矩形当前有效。 如果不是,它会调用 super 来发送消息在响应者链上。
如果响应方实现了此方法,但决定不处理特定事件,它应该调用此方法。
override func cursorUpdate(with event: NSEvent) {
// Convert mouse location to the view coordinates
let mouseLocation = convert(event.locationInWindow, from: nil)
// Check if the mouse location lies within the rect being tracked
if trackingRect.contains(mouseLocation) {
// Set the custom cursor
NSCursor.openHand.set()
} else {
// Reset the cursor
super.cursorUpdate(with: event)
}
}
我只是通过谷歌搜索遇到了这个问题,所以我想我会发布我的解决方案。
- Subclass the NSTextView/NSTextField.
-
按照文档中的步骤创建 NSTrackingArea。应如下所示。将此代码放在子类的 init 方法中(同时添加
updateTrackingAreas
方法(:NSTrackingArea *trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds options:(NSTrackingMouseMoved | NSTrackingActiveInKeyWindow) owner:self userInfo:nil]; [self addTrackingArea:trackingArea]; self.trackingArea = trackingArea;
-
现在您需要将
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]; } }
注意:self.popUpButton
是 NSTextView/NSTextField 的子视图按钮。
就是这样!它最终不会太难 - 只是不得不使用mouseMoved:
而不是cursorUpdate:
。我花了几个小时才弄清楚这一点,希望有人可以使用它。