2016-01-11 10 views
7

Ho lavorato a una piccola immagine per caricare l'app per menubar per OS X. Ho creato una sottoclasse personalizzata NSView per gli elementi caricati.NSViewController lento a registrare gli eventi del mouse?

Ecco come si presenta di default:

Ravioli - not hovered

Gli eventi del mouse sono gestite dal di NSViewController nel modo seguente vista:

import Cocoa 

class MenuItemController: NSViewController { 

    private var trackingArea: NSTrackingArea? 

    override func mouseEntered(theEvent: NSEvent) { 
     if let v = self.view as? MenuItemView { 
      v.shouldHighlight = true 
      v.needsDisplay = true 
     } 
    } 

    override func mouseExited(theEvent: NSEvent) { 
     if let v = self.view as? MenuItemView { 
      v.shouldHighlight = false 
      v.needsDisplay = true 
     } 
    } 


    override func viewDidLoad() { 
     super.viewDidLoad() 

     if (trackingArea == nil) { 
      trackingArea = NSTrackingArea(rect: self.view.bounds, options: [.ActiveAlways, .MouseEnteredAndExited], owner: self, userInfo: nil) 
      self.view.addTrackingArea(trackingArea!) 
     } 

     /* rest of the code... */ 
    } 

} 

Funziona bene fino a quando muovo il cursore veloce sopra gli articoli. Sembra che l'evento mouseExited() non viene chiamato, e la vista rimane con uno sfondo blu (mouse è in realtà sul pulsante Esci):

Ravioli bug

Ho anche cercato di spostare il movimentazione nel NSView mouse, ma con stesso risultato. Apprezzo qualsiasi input! Grazie!

+0

Questo suona molto simile ad altri problemi di prestazioni OSX lenti in cui l'attivazione dell'animazione core migliora le prestazioni. Dai un'occhiata a http://stackoverflow.com/questions/26696644/nstableview-view-based-scrolling-performance – Michael

risposta

2

A mio parere, Apple ha riscontrato bug in questo settore.

Supponendo di aggiornare l'area di rilevamento in base a apple docs, aggiungendo questa correzione aggiuntiva potrebbe risolvere il problema ... lo risolve per me in molti casi. Ho verificato nel mouseMovuto/mouseModifica inversa che il cursore del mouse si trova ancora all'interno della cornice delle mie viste e, in caso contrario, chiama mouseExited: myself.

- (void) adjustTrackingArea 
{ 
    if (trackingArea) 
    { 
     [self removeTrackingArea:trackingArea]; 
     [trackingArea release]; 
    } 

    // determine the tracking options 
    NSTrackingAreaOptions trackingOptions = // NSTrackingEnabledDuringMouseDrag | // don't track during drag 
    NSTrackingMouseMoved | 
    NSTrackingMouseEnteredAndExited | 
    //NSTrackingActiveInActiveApp | NSTrackingActiveInKeyWindow | NSTrackingActiveWhenFirstResponder | 
    NSTrackingActiveAlways; 
    NSRect theRect = [self visibleRect]; 
    trackingArea = [[NSTrackingArea alloc] 
        initWithRect: theRect 
        options: trackingOptions 
        owner: self 
        userInfo: nil]; 
    [self addTrackingArea:trackingArea]; 
} 


- (void)resetCursorRects 
{ 
    [self adjustTrackingArea]; 
} 
- (void)mouseEntered:(NSEvent *)ev 
{ 
    [self setNeedsDisplay:YES]; 
    // make sure current mouse cursor location remains under the mouse cursor 
    NSPoint cursorPt = [self convertPoint:[[self window] mouseLocationOutsideOfEventStream] fromView:NULL]; 

    // apple bug!!! 
    //NSPoint cursorPt2 = [self convertPointFromBase:[ev locationInWindow]]; 
    //if (cursorPt.x != cursorPt2.x) 
    // NSLog(@"hello old cursorPt"); 
    NSRect r = [self frame]; 
    if (cursorPt.x > NSMaxX(r) || cursorPt.x < 0) 
    { 
     [self mouseExited:ev]; 
     //cursorPt.x = [self convertPointFromBase:[ev locationInWindow]]; 
     //if (cursorPt.x > NSMaxX(r) || cursorPt.x < r.origin.x) 
     return; 
    } 

    ... your custom stuff here ... 
} 

- (void)mouseExited:(NSEvent *)theEvent 
{ 
    if (isTrackingCursor == NO) 
     return; 

    [[NSCursor arrowCursor] set]; 
    isTrackingCursor = NO; 
    [self setNeedsDisplay:YES]; 
} 

- (void)mouseMoved:(NSEvent *)theEvent 
{ 
    [self mouseEntered:theEvent]; 
} 
+0

Sono stato in grado di trovare una soluzione basata su questa risposta. Grazie Keith! – Zoltan

1

Non capisco se si sta installando un NSTrackingArea per tutta la finestra (in questo menu caso) o per ogni elemento. Se stai facendo il secondo, non farlo, o passerai un tempo infinito per correggere i problemi che stai vedendo. Il modo in cui ho gestito questo comportamento bug è quello di creare un NSTrackingArea per l'intera finestra e mi immagino dove sia il mouse e gestisco personalmente l'evidenziazione di ogni oggetto. So che questo non è l'ideale, ma questo era l'unico modo in cui ero in grado di risolverlo dopo essermi buttato in testa per tre giorni.

+0

Anche questa è una buona risposta ... Io uso un metodo simile per implementare un sistema di tool-tool simile a un browser nella parte inferiore della mia finestra. (Gli utenti esperti non amano i tooltip stile pop-up su GUI che usano spesso) –

0

è possibile tenere traccia che era il vecchio attiva menuitem e impostare la gestione di conseguenza, qualcosa come:

override func mouseEntered(theEvent: NSEvent) { 
     if let v = self.view as? MenuItemView { 
      lastEntered.shouldHighLight = false 
      lastEntered.needsDisplay = true 
      lastEntered = v; 
      lastEntered.shouldHighLight = true 
      lastEntered.needsDisplay = true 
     } 
    } 

Così si è sicuri che al massimo uno sarà attiva.

+0

Grazie per la risposta! Questa è una buona soluzione per spostare il cursore sugli elementi, ma se sposto il mouse fuori dalla finestra senza inserire altro (o un NSMenuItem nativo), il problema rimane. :/ – Zoltan

+0

Questo è solo uno scheletro, devi gestire altri eventi ... –

Problemi correlati