2011-01-07 19 views
18

マウスの位置がNSViewのrect内にあるかどうかを調べる必要があります。マウスがビュー上にあるかどうかを見つける方法

私はNSPointInRect(point, rect)を使用したいと思いますが、私はrect座標を画面座標に変換する必要がありますが、わかりません。どんな助けでも大歓迎です!このような

+0

理由を教えてください。一般的に、このテクニックは素晴らしいアイデアではありませんが、あなたが何を書いているのかを知らないと言うのは難しいです。 –

答えて

22

使用のNSViewのconvertPoint:fromView:ウィンドウ内のポイントを転化するfromViewゼロとして有する方法は、ビューの座標系に座標。

マウスポインターをビューの座標系に変換した後、NSViewInRectの代わりにNSViewのマウス:inRect:メソッドを使用します。前者も座標系が反転しているためです。

また、Tracking Area Objectを使用することもできます。

+1

NSTrackingAreaは私が探していたものでした!ありがとうございました! –

+1

私はこれを結びつけていますが、convertPoint関数は実際には最初のパラメータとしてNSPointオブジェクトを要求します。私は何をすべきですか?どうぞ黙ってください。 –

+2

NSViewのmouse:inRect: 'の' NSRect'引数に 'self.bounds'を渡して、' self.frame'を送信すると座標をオフセットする必要があることを付け加えたいと思います。 – ColdSteel

33

何かがあなたのために働く必要があります。

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 
} 

私は個人的には、この多くのローカル変数を使用していないが、うまくいけば、これはこの例をより明確に。

+0

NSEventにはすでに[イベントlocationInWindow]がありますので、最初の3行は冗長です –

+1

locationInWindowはほとんどの場合動作します。しかし、これはアップルのドキュメントにあります。「NSMouseMovedと他のイベントがあると、受信者はnilウィンドウを持つことができます(つまり、windowはnilを返します)。この場合、locationInWindowは画面座標でイベント位置を返します。したがって、locationInWindowに依存しない方がより堅牢であるように見えます。すでにイベントがあった場合は、locationInWindowが必ず使用する呼び出しになります。私の答えのメソッドは、あなたがまだイベントオブジェクトを持っていなくても動作します。 –

5

マウスを利用していくつかのコード:inRect:(推奨方法;反転した座標を占めている)これらの答えの

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

なしビューは、長方形ではないかもしれないことを考慮していません。

これは、非長方形のビューでも機能する普遍的な方法です。ウォッチフェイスや複雑なパスの形状を考えてください。

このコードスニペットは、globalPoint(別名globalToLocal)からlocalPointを提供します。 (0,0のウィンドウ空間のGlobalPoint)引数を "toView"に変更すると、 "localToGlobal"ポイントが得られます。

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

ポイントがパス内にあるかどうかにかかわらず、蛇行コードは真または偽を返します。

CGPathContainsPoint(someCGPath,nil,localPoint,true)

注:

(self.window?.mouseLocationOutsideOfEventStream)! 

: より正しいがあるかもしれません でaPointがhitTestでパラメータ由来globalPointあり、それはまた、由来することができますこれを行う方法。しかし、これはうまくいき、フリップされたビューを気にしません。

+0

上記のアプローチでもなお落とし穴があります。たとえばNSViewsの階層内でTextFieldをhitTestingするためのきれいなソリューションを見つけるのに苦労しました。 AppleがtextFieldをhitTestingするときには、彼らの戦術を変えるので、あなたも採用しなければなりません。私はそれを働かせ、それをかなりきれいにする方法を見つけました。しかし、階層内の各ビュー内の各hitTestPointをフリップしたり、オフセットしたりする可能性があります。これは、Appleがそのコンポーネントで行うことのようです。私が使用するすべてのViewクラスに含まれているメソッドに追加するだけです。 – eonist

+0

これは非常に「混乱した」記事ですが、試してはいけないことについてのいくつかの洞察を与えるかもしれません。 http://stylekit.org/blog/2016/01/28/Hit-testing-sub-views/(基本的には、hitTestingのリサーチのすべてのメモ)Iveの後に移動し、hitTestingについてはクリーンなワークフローがあります。 – eonist

関連する問題