2011-01-07 10 views
18

Ich muss herausfinden, ob die Mausposition in einem NSView-Rect ist.So finden Sie, ob die Maus über einer Ansicht ist

Ich würde NSPointInRect(point, rect) verwenden, aber ich müsste die rect Koordinaten in Bildschirmkoordinaten konvertieren und ich bin mir nicht sicher, wie. Jede Hilfe würde sehr geschätzt werden!

+0

Können Sie uns einen Grund geben, warum? Im Allgemeinen ist diese Technik keine gute Idee, aber es ist schwer zu sagen, ohne zu wissen, was Sie schreiben. –

Antwort

22

Verwenden des NSView convertPoint: fromView: Methode mit fromView als nil einen Punkt im Fenster verdeckte Koordinaten in einem Koordinatensystem der Ansicht. inRect: Methode statt NSPointInRect als die ehemaligen auch für Konten blätterten Koordinatensysteme

Nach der Maus Punkt Umwandlung in das Koordinatensystem der Ansicht, würde ich NSView die Maus verwenden.

Alternativ können Sie auch Tracking Area Object verwenden.

+1

NSTrackingArea war GENAU was ich suchte! Vielen Dank! –

+1

ich bin dies binden ... aber die ConvertPoint-Funktion fragt tatsächlich nach einem NSPoint-Objekt als seinen ersten Parameter. Was soll ich geben? Bitte zusammen ausführen. –

+2

Ich möchte hinzufügen, dass Sie "self.bounds" für das 'NSRect' Argument in der' NSView's Maus übergeben: inRect: 'Senden der' self.frame' wird die Koordinaten versetzen. – ColdSteel

33

So etwas sollte für Sie arbeiten:

NSView* myView; // The view you are converting coordinates to 
NSPoint globalLocation = [ NSEvent mouseLocation ]; 
NSPoint windowLocation = [ [ myView window ] convertScreenToBase: globalLocation ]; 
NSPoint viewLocation = [ myView convertPoint: windowLocation fromView: nil ]; 
if(NSPointInRect(viewLocation, [ myView bounds ])) { 
    // Do your thing here 
} 

ich persönlich nicht so viele lokale Variablen verwenden, aber hoffentlich dieses Beispiel deutlicher machen.

+0

NSEvent hat bereits ein [event locationInWindow], sodass die ersten drei Zeilen redundant sind –

+1

locationInWindow würde wahrscheinlich die meiste Zeit arbeiten. Aber das ist aus der Apple-Dokumentation: "Mit NSMouseMoved und möglicherweise anderen Ereignissen kann der Empfänger ein Null-Fenster haben (dh das Fenster gibt nil zurück). In diesem Fall gibt locationInWindow den Ereignisort in Bildschirmkoordinaten zurück." Es scheint also so, als wäre die Verwendung von locationInWindow nicht robuster.locationInWindow wäre sicherlich der Aufruf zu verwenden, wenn Sie bereits eine Veranstaltung hatten. Die Methode in meiner Antwort funktioniert auch dann, wenn Sie noch kein Ereignisobjekt haben. –

5

Einige Code Verwendung von Maus zu machen: inRect: (die empfohlene Art und Weise, die für blätterte Koordinaten-Konten)

CGPoint point = [self convertPoint:[event locationInWindow] fromView:nil]; 
CGRect rect = [self bounds]; 
if ([self mouse:point inRect:rect]) { 
} 
1

Keine dieser Antworten zu berücksichtigen, dass eine Ansicht nicht rechteckig sein könnte.

Hier ist eine universelle Methode, die auch auf nicht rechteckigen Ansichten funktioniert. Denken Sie an Zifferblatt oder eine komplexe Pfadform.

Dieses Code-Snippet gibt Ihnen einen localPoint von einem globalPoint (aka globalToLocal). (GlobalPoint in 0,0 window space) Wenn Sie das Argument in "toView" ändern, erhalten Sie einen "localToGlobal" -Punkt.

Der untere Code würde wahr oder falsch zurückgeben, wenn der Punkt innerhalb des Pfads liegt oder nicht.

CGPathContainsPoint(someCGPath,nil,localPoint,true)

HINWEIS:

(self.window?.mouseLocationOutsideOfEventStream)! 

HINWEIS: Apoint ist ein global aus dem Parameter in hitTest abgeleitet, es kann auch abgeleitet werden aus Es könnte ein richtiger Art und Weise dies zu tun. Aber das funktioniert und kümmert sich nicht um umgedrehte Ansichten.

+0

Es gibt immer noch Fallstricke, selbst mit dem oben beschriebenen Ansatz. Ich hatte eine Menge Probleme, eine saubere Lösung für hitTesting der TextField innerhalb einer Hierarchie von NSViews zum Beispiel zu finden. Da apple ihre Taktik ändert, wenn es um hitTesting der TextField geht, müssen Sie auch adoptieren. Ich habe einen Weg gefunden, das funktioniert und es ist ziemlich sauber. Es ist jedoch sehr wahrscheinlich, dass Sie jeden hitTestPoint in jeder Ansicht in der Hierarchie spiegeln und versetzen, da dies scheint, was Apple mit seinen Komponenten macht. Fügen Sie es einfach einer Methode hinzu, die in jeder von mir verwendeten View-Klasse enthalten ist. – eonist

+0

Dies ist ein sehr "unorganisierter" Artikel, aber es kann Ihnen einen Einblick geben, was Sie nicht versuchen sollten. http://stykit.org/blog/2016/01/28/Hit-testing-sub-views/ (es ist im Grunde alle meine Notizen aus hitTesting Forschung) Ive seit dem weiter fortgeschritten und haben einen sauberen Workflow, wenn es um hitTesting geht. – eonist

Verwandte Themen