あなたがまだ答えを探しているかどうかはわかりません。私は最近、あなたが説明したような非常によく似た機能をたまたま必要とするプロジェクトに取り組んでいました。
NSTextView のサブクラス内で次のことができます。
呼び出す関数は次のとおりです: showRelativeToRect:ofView:preferredEdge:
rect は NSTextView 座標系を使用した NSTextView 内の rect であり、ofView は NSTextView であり、preferredEdge はこのポップオーバーをフックするエッジです。
さて、あなたは PopOver のものをキャレットの下に表示したいと言っています。まあ、彼に Rect を与える必要があります。Point では十分ではありません。NSTextView には selectedRange と呼ばれるセレクターがあり、選択したテキストの範囲を提供します。これを使用してキャレットを見つけることができます。
次に、firstRectForCharacterRange を呼び出します (クラスは NSTextInputClient をデリゲートする必要があります)。このメソッドは、NSTextView 内の選択されたテキストの画面座標を返します。次に、それらを NSTextView 座標系に変換します。正しい位置。これが私のコードです。
NSRect rect = [self firstRectForCharacterRange:[self selectedRange]]; //screen coordinates
// Convert the NSAdvancedTextView bounds rect to screen coordinates
NSRect textViewBounds = [self convertRectToBase:[self bounds]];
textViewBounds.origin = [[self window] convertBaseToScreen:textViewBounds.origin];
rect.origin.x -= textViewBounds.origin.x;
rect.origin.y -= textViewBounds.origin.y;
rect.origin.y = textViewBounds.size.height - rect.origin.y - 10; //this 10 is tricky, if without, my control shows a little below the text, which makes it ugly.
NSLog(@"rect %@", NSStringFromRect(rect));
NSLog(@"bounds %@", NSStringFromRect([self bounds]));
if([popover isShown] == false)
[popover showRelativeToRect:rect
ofView:self preferredEdge:NSMaxYEdge];
これが結果です。
私が疑問に思っているのは、システム関数を使用して変換する方法があれば、convertRect:toView を試したのですが、このメソッドはデリゲートで記述されているため、NSTextView は常に (0,0) の座標系を持っているということです。 、この方法は役に立たない。
