Macos 在NSTextView上更改NSView的NSCursor
发现了一个与我类似的问题, 但我的问题似乎更多地与视图层次结构有关 我有一个NSTextView,然后作为同级视图,它上面还有几个其他NSVIEW 与上面链接的问题类似,我设置了一个跟踪区域,并按如下方式应用光标:Macos 在NSTextView上更改NSView的NSCursor,macos,swift,cocoa,Macos,Swift,Cocoa,发现了一个与我类似的问题, 但我的问题似乎更多地与视图层次结构有关 我有一个NSTextView,然后作为同级视图,它上面还有几个其他NSVIEW 与上面链接的问题类似,我设置了一个跟踪区域,并按如下方式应用光标: class CursorChangingView: NSView { override func updateTrackingAreas() { let trackingArea = NSTrackingArea(rect: } overr
class CursorChangingView: NSView {
override func updateTrackingAreas() {
let trackingArea = NSTrackingArea(rect:
}
override func cursorUpdate(event: NSEvent) {
NSCursor.arrowCursor().set()
}
}
它在悬停时似乎可以工作,但会立即返回到,这是此光标或更改视图下NSTextView的默认光标
这是在将光标悬停在某个NSView上时应用更改光标的正确方法吗?它下面的NSTextView是否覆盖了我的覆盖?您所需要的只是对自定义视图进行子类化,覆盖awakeFromNib方法,为[.mouseMoved,.activeAlways]事件添加自定义跟踪区域:那里。无需覆盖
resetCursorRects
和/或updateTrackingAreas
。您只需重写mouseMoved方法并在其中设置所需的光标:
关于discardCursorRects
方法的说明:
从文件中
您永远不需要直接调用此方法
Xcode 9•Swift 4
import Cocoa
class CursorChangingView: NSView {
override func awakeFromNib() {
addTrackingArea(NSTrackingArea(rect: bounds, options: [.activeAlways, .mouseMoved], owner: self, userInfo: nil))
wantsLayer = true
layer?.backgroundColor = NSColor.cyan.cgColor
layer?.borderColor = NSColor.black.cgColor
layer?.borderWidth = 1
}
@objc override func mouseMoved(with theEvent: NSEvent) {
NSCursor.pointingHand.set()
}
}
谢谢@Leo Dabus的回答, 但是我成功地解决了这个问题,所以我也会发布我的答案 在我的例子中,由于某种原因,
mouseEntered
和mouseEntered
根本不起作用
下面是我的代码,它最终实现了:
class CursorChangingView: NSView {
let trackingArea: NSTrackingArea?
func setupTracking() {
if self.trackingArea == nil {
self.trackingArea = NSTrackingArea(rect: self.bounds, options: NSTrackingAreaOptions.ActiveAlways | NSTrackingAreaOptions.MouseMoved | NSTrackingAreaOptions.CursorUpdate | NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInActiveApp, owner: self, userInfo: nil)
self.addTrackingArea(self.trackingArea!)
}
}
override func updateTrackingAreas() {
self.trackingArea = NSTrackingArea(rect: self.bounds, options: NSTrackingAreaOptions.ActiveAlways | NSTrackingAreaOptions.CursorUpdate | NSTrackingAreaOptions.MouseEnteredAndExited | NSTrackingAreaOptions.ActiveInActiveApp, owner: self, userInfo: nil)
self.addTrackingArea(self.trackingArea!)
}
override func resetCursorRects() {
self.discardCursorRects()
self.addCursorRect(self.bounds, cursor: NSCursor.arrowCursor())
}
override func mouseMoved(theEvent: NSEvent) {
NSCursor.arrowCursor().set()
}
}
这可能有点过分,但有效,因此我将把它作为我自己的解决方案与大家分享。一些重要注意事项:
- 在
或类似事件上调用mouseMoved
时要小心,否则光标可能会被基类实现重置super
- 仅在父视图大小更改时重置跟踪区域;如果您试图通过覆盖
来实现这一点,那么这种情况将一直发生,这并不好layout()
import Cocoa
final class MouseTrackingTextView: NSTextView {
// MARK: - Lifecycle
override func awakeFromNib() {
setupTrackingArea()
}
// MARK: - Resizing
// Call this in your controller's `viewDidLayout`
// so it only gets called when the view resizes
func superviewResized() {
resetTrackingArea()
}
// MARK: - Mouse Events
override func resetCursorRects() {
addCursorRect(bounds, cursor: cursorType)
}
override func mouseMoved(with event: NSEvent) {
cursorType.set()
}
// MARK: - Private Properties
private var currentTrackingArea: NSTrackingArea?
private var cursorType: NSCursor {
return isEditable ? .iBeam : .pointingHand
}
// MARK: - Private API
private func setupTrackingArea() {
let trackingArea = NSTrackingArea(rect: bounds,
options: [.activeAlways, .mouseMoved],
owner: self, userInfo: nil)
currentTrackingArea = trackingArea
addTrackingArea(trackingArea)
}
private func resetTrackingArea() {
if let trackingArea = currentTrackingArea {
removeTrackingArea(trackingArea)
}
setupTrackingArea()
}
}
在我的例子中,当
CursorChangingView
位于NSTextView
上方时,此选项仍会闪烁。你是怎么摆脱的?还有,第二次创建跟踪时,你不再跟踪。mouseMoved
对我不起作用。如果自定义视图下面的文本字段具有first responder,则光标仍会更改回IBeam