2012-08-22 134 views
3

我試圖在從NIB加載的窗口表中更改NSTextField的鼠標光標。無法更改NSTextField的鼠標光標

繼文檔後,我已將子類別NSTextField和實施resetCursorRects

- (void) resetCursorRects { 
    [self addCursorRect:[self bounds] cursor:[NSCursor pointingHandCursor]]; 
} 

這從來沒有被稱爲。甚至沒有加入後的NSWindowViewController如下:

- (void) windowDidLoad { 
    [self.window invalidateCursorRectsForView:self.linkTextField]; 
} 

我也通過增加在NSTextField子下面有一個跟蹤區域的嘗試:

- (void) awakeFromNib { 
    NSTrackingArea* trackingArea = [[NSTrackingArea alloc] initWithRect:self.bounds 
               options:(NSTrackingCursorUpdate | NSTrackingActiveAlways) 
                owner:self 
               userInfo:nil]; 
    [self addTrackingArea:trackingArea]; 
} 

- (void)cursorUpdate:(NSEvent *)theEvent { 
    [[NSCursor pointingHandCursor] set]; 
} 

也不能工作。我究竟做錯了什麼?

+0

你解決這個問題?我有類似的問題。 – Jensen

+0

@Jensen Nope。你在嘗試不同的東西嗎? – hpique

+0

只是通過在其超級視圖中覆蓋mouseMoved方法來解決此問題。 – Jensen

回答

0

我有同樣的問題,cursorUpdate方法被稱爲每次光標進入跟蹤區域,但光標被設置回其他地方,可能是它的超級視圖。

我設法通過重寫mouseMoved方法來解決它。

// In the textfield subclass: 
- (void)mouseEntered:(NSEvent *)theEvent { 
    [super mouseEntered:theEvent]; 
    self.isMouseIn = YES; 
} 

- (void)mouseExited:(NSEvent *)theEvent { 
    [super mouseExited:theEvent]; 
    self.isMouseIn = NO; 
} 


//In the superview of the textfield: 
- (void)mouseMoved:(NSEvent *)theEvent { 
    if (self.hoverButton.isMouseIn) { 
     [[NSCursor pointingHandCursor] set]; 
    } 
    [super mouseMoved:theEvent]; 
} 

我在windowController類overrided的的mouseMoved方法,但重寫上海華應該工作。

5

Clickable links with NSTextField

我得到了這個工作繼承NSTextField爲後面提到的:

- (void)resetCursorRects { 
    [self addCursorRect:[self bounds] cursor:[NSCursor pointingHandCursor]]; 
} 
+0

太棒了!這效果很好! ;) – Tommy

+0

簡直太棒了!謝謝。 – Christophe

0

NSTextView似乎通過其-(void)mouseMoved:(NSEvent*)theEvent方法來處理光標。另外,當NSTextView成爲第一響應者時,RunLoop中的一些私有代碼似乎強制光標移到IBeamCursor,而沒有給我們選擇。下面是圍繞這些限制工作的子類:

@interface MyTextView : NSTextView { 
    NSTrackingArea* area; 
    BOOL mouseInside; 
} 

@property(nonatomic, retain) NSTrackingArea* area; 

@end 


@implementation MyTextView 

@synthesize area; 

- (void)setArea:(NSTrackingArea *)newArea 
{ 
    [newArea retain]; 
    if (area) { 
     [self removeTrackingArea:area]; 
     [area release]; 
    } 
    if (newArea) { 
     [self addTrackingArea:newArea]; 
    } 
    area = newArea; 
} 

- (BOOL)becomeFirstResponder 
{ 
    NSRect rect = <insert the tracking rect where you want to have a special cursor>; 
    self.area = [[[NSTrackingArea alloc] initWithRect:rect options:NSTrackingMouseEnteredAndExited | NSTrackingActiveWhenFirstResponder owner:self userInfo:nil] autorelease]; 
    NSEvent* ev = [NSApp currentEvent]; 
    if (NSPointInRect([self convertPoint:ev.locationInWindow fromView:nil], self.bounds)) { 
     mouseInside = YES; 
     // This is a workaround for the private call that resets the IBeamCursor 
     [[NSCursor arrowCursor] performSelector:@selector(set) withObject:nil afterDelay:0]; 
    } 
} 

- (void)mouseEntered:(NSEvent *)theEvent 
{ 
    [super mouseEntered:theEvent]; 
    [[NSCursor arrowCursor] set]; 
    mouseInside = YES; 
} 

- (void)mouseExited:(NSEvent *)theEvent 
{ 
    [super mouseExited:theEvent]; 
    mouseInside = NO; 
} 

- (void)mouseMoved:(NSEvent *)theEvent 
{ 
    si (!mouseInside) { 
     // We only forward the mouseMoved event when the mouse is outside the zone for which we control the cursor 
     [super mouseMoved:theEvent]; 
    } 
} 

- (oneway void)dealloc 
{ 
    [area release]; 
    [super dealloc]; 
} 

@end 
1

我寫了上面的答案的雨燕2.0版本,並使它可作爲GitHub sample project found here

而且,即使它設置的NSTextField,概念應當與任何來自NSResponder子類的工作(這是mouseEnteredbecomeFirstResponder來自)。

這是我寫的代碼的膽量:

import Cocoa 

class CCTextField: NSTextField { 

    var myColorCursor : NSCursor? 

    var mouseIn : Bool = false 

    var trackingArea : NSTrackingArea? 

    override func awakeFromNib() 
    { 
     myColorCursor = NSCursor.init(image: NSImage(named:"heart")!, hotSpot: NSMakePoint(0.0, 0.0)) 
    } 

    override func resetCursorRects() { 
     if let colorCursor = myColorCursor { 
      self.addCursorRect(self.bounds, cursor: colorCursor) 
     } 
    } 

    override func mouseEntered(theEvent: NSEvent) { 
     super.mouseEntered(theEvent) 
     self.mouseIn = true 
    } 

    override func mouseExited(theEvent: NSEvent) { 
     super.mouseExited(theEvent) 
     self.mouseIn = false 
    } 

    override func mouseMoved(theEvent: NSEvent) { 
     if self.mouseIn { 
      myColorCursor?.set() 
     } 
     super.mouseMoved(theEvent) 
    } 

    func setArea(areaToSet: NSTrackingArea?) 
    { 
     if let formerArea = trackingArea { 
      self.removeTrackingArea(formerArea) 
     } 

     if let newArea = areaToSet { 
      self.addTrackingArea(newArea) 
     } 
     trackingArea = areaToSet 
    } 

    override func becomeFirstResponder() -> Bool { 
     let rect = self.bounds 
     let trackingArea = NSTrackingArea.init(rect: rect, options: [NSTrackingAreaOptions.MouseEnteredAndExited, NSTrackingAreaOptions.ActiveAlways], owner: self, userInfo: nil) 

     // keep track of where the mouse is within our text field 
     self.setArea(trackingArea) 

     if let ev = NSApp.currentEvent { 
      if NSPointInRect(self.convertPoint(ev.locationInWindow, fromView: nil), self.bounds) { 
       self.mouseIn = true 
       myColorCursor?.set() 
      } 
     } 
     return true 
    } 
} 
0

這個工作對我來說:

class TextField: NSTextField { 
    override func becomeFirstResponder() -> Bool { 
     addTrackingAreaIfNeeded() 
     return super.becomeFirstResponder() 
    } 
    override func mouseMoved(with event: NSEvent) { 
     super.mouseMoved(with: event) 
     NSCursor.pointingHand.set() 
    } 
    private func addTrackingAreaIfNeeded() { 
     if trackingAreas.isEmpty { 
      let area = NSTrackingArea(rect: bounds, options: [.mouseEnteredAndExited, .activeAlways], owner: self, userInfo: nil) 
      addTrackingArea(area) 
     } 
    } 
}