2011-01-07 19 views
18

Muszę znaleźć, czy pozycja myszy znajduje się w prostokącie NSView.Jak sprawdzić, czy mysz znajduje się nad widokiem?

Użyłbym NSPointInRect(point, rect), ale musiałbym przekonwertować współrzędne prostokątne na współrzędne ekranu i nie jestem pewien jak. Każda pomoc będzie doceniona!

+0

Czy możesz podać nam powód dlaczego? Zasadniczo ta technika nie jest świetnym pomysłem, ale trudno powiedzieć, nie wiedząc, co piszesz. –

Odpowiedz

22

Przymież NSView w convertPoint: fromView: sposób z fromView jak zero tajnych punktu w okienku współrzędnych układu współrzędnych danego widoku danych.

Po konwersji punktu myszy na układ współrzędnych widoku, użyłbym myszy NSView: : inRect: metoda zamiast NSPointInRect jako pierwsza uwzględnia również odwrócone układy współrzędnych.

Alternatywnie można użyć Tracking Area Object.

+1

NSTrackingArea było DOKŁADNIE tym, czego szukałem! Dziękuję Ci! –

+1

Wiążę to ... ale funkcja convertPoint faktycznie prosi o obiekt NSPoint jako swój pierwszy parametr. Co powinienem dać? proszę wymyślić. –

+2

Chciałbym dodać, że należy przekazać 'self.bounds' dla argumentu' NSRect' w myszy 'NSView's: inRect:' wysłanie 'self.frame' zrównoważy współrzędne. – ColdSteel

33

Coś jak to powinno działać dla Ciebie:

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 
} 

Osobiście nie używać to wiele zmiennych lokalnych, ale mam nadzieję, że tego uczynić ten przykład jaśniejszy.

+0

NSEvent ma już [event locationInWindow], więc pierwsze 3 linie są zbędne –

+1

locationInWindow prawdopodobnie pracowałby przez większość czasu. Ale jest to z dokumentacji Apple: "Z NSMouseMoved i ewentualnie innymi zdarzeniami, odbiornik może mieć zerowe okno (to jest okno zwraca zero) .W tym przypadku locationInWindow zwraca lokalizację zdarzenia na współrzędnych ekranu." Wygląda więc na to, że nie poleganie na locationInWindow może być bardziej niezawodne.locationInWindow z pewnością byłby wezwaniem do użycia, jeśli już miałeś wydarzenie. Metoda w mojej odpowiedzi zadziała, nawet jeśli nie masz jeszcze obiektu zdarzenia. –

5

Niektóre kodu z wykorzystaniem myszy: inRect: (zalecany sposób, że stanowi przerzucony współrzędnych)

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

Żadna z tych odpowiedzi wziąć pod uwagę, że widok nie może być prostokątny.

Oto uniwersalna metoda, która działa również w widokach innych niż prostokątne. Pomyśl o tarczy zegarka lub o skomplikowanym kształcie ścieżki.

Ten fragment kodu podaje lokalny punkt z punktu globalnego (inaczej globalToLocal). (GlobalPoint w przestrzeni okna 0,0) Jeśli zmienisz argument na "toView", otrzymasz punkt "localToGlobal".

let localPoint = convertPoint(aPoint, fromView: self.window?.contentView)  

Kod poniżej zwróciłby wartość true lub false, jeśli punkt znajdował się wewnątrz ścieżki lub nie.

CGPathContainsPoint(someCGPath,nil,localPoint,true)

UWAGA: Apoint jest globalPoint pochodzi od parametru w hitTest, może również pochodzić z:

(self.window?.mouseLocationOutsideOfEventStream)! 

UWAGA: Nie może być bardziej poprawne sposób robienia tego. Ale to działa i nie dba o odwrócone widoki.

+0

Nadal istnieją pułapki nawet w przypadku podejścia opisanego powyżej. Miałem wiele problemów ze znalezieniem czystego rozwiązania dla hitTesting TextField wewnątrz hierarchii NSView na przykład. Odkąd jabłko zmienia taktykę, jeśli chodzi o hitTestowanie pola tekstowego, które również musisz przyjąć. Znalazłem sposób, żeby to działało i było całkiem czyste. Jednak prawdopodobnie zacznie się odwracać i przesuwać każdy hitTestPoint w każdym widoku w hierarchii, ponieważ wydaje się, że to, co robi jabłko ze swoimi komponentami. Po prostu dodaj ją do metody zawartej w każdej używanej klasie View. – eonist

+0

To jest bardzo "niezorganizowany" artykuł, ale może dać ci wgląd w to, czego nie spróbować. http://stylekit.org/blog/2016/01/28/Hit-testing-sub-views/ (to w zasadzie wszystkie moje notatki z badań hitTesting) Odkąd przeszedłem i mam czysty przepływ pracy, jeśli chodzi o hitTesting. – eonist

Powiązane problemy