3

我知道为了显示一个弹出框我需要一个 NSView,但我不认为有一个与插入符号相关联(在 NSTextView 内)。有没有办法在插入符号下方显示 NSPopover?

我试图分配一个 NSView 并使用它定位它(NSRect)boundingRectForGlyphRange:(NSRange)glyphRange inTextContainer:(NSTextContainer *)container,但弹出框不会出现(并且有一个原因,该方法返回NSRect: {{0, 0}, {0, 0}})。

4

1 回答 1

10

我不确定你是否还在寻找答案。我最近正在从事一个项目,该项目恰好需要您描述的非常相似的功能。

您可以在 NSTextView 的子类中执行以下操作:

你要调用的函数是:showRelativeToRect:ofView:preferredEdge:

rect 将是 NSTextView 内部的一个矩形,使用 NSTextView 坐标系,ofView 是 NSTextView,preferredEdge 是你希望这个 popover 东西挂钩的边缘。

现在,您说您希望在插入符号下显示 PopOver 事物,那么您必须给他一个 Rect,一个 Point 是不够的。NSTextView 有一个名为 selectedRange 的选择器,它为您提供所选文本的范围,您可以使用它来定位您的插入符号。

接下来就是调用firstRectForCharacterRange(该类必须委托NSTextInputClient),这个方法会返回一个NSTextView里面选中文本的屏幕坐标,然后你把它们转换成NSTextView坐标系,你就可以在上面展示NSPopover这个东西了一个正确的位置。这是我这样做的代码。

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) ,这使得这种方法毫无用处。

NSPopover 显示在所选文本下方

于 2011-12-26T15:37:04.307 回答