1

语境

让我们P成为一个 NSPopover 并view成为一个 NSView ,它是一个包含在P.

我需要的

我想获取框架view并将其转换为屏幕的坐标系。通常,您会这样做:

NSRect frameRelativeToWindow = [self convertRect:self.frame relativeToView:nil]; 
[self.window convertRectToScreen:frameRelativeToWindow];

但是,因为view是在一个 NSPopover 中,所以它的window属性是 nil 并且上面的方法会返回 NSZeroRect: [0, 0, 0, 0]

那么,如果视图位于 NSPopover 中,如何在屏幕坐标中获取视图的框架?

笔记:

  1. NSPopover 在屏幕上并且可见。
  2. 我试图将其框架转换为屏幕坐标的视图不是 NSPopover 或其 contentView 的直接子视图。有问题的视图实际上是 NSClipView 中的 NSScrollView 中的 NSTableView 中的 NSTableCellView 中的自定义 NSView。clipView 是 NSPopover 的 contentView 的直接子视图。
  3. 在普通的 NSWindow 中,您可以获取任何子视图并调用[self window]以获取包含的 NSWindow 对象。然而,在弹出窗口中这样做会返回 nil。
4

2 回答 2

1

您计算屏幕坐标的方法是正确的(只是不要忘记首先使用将视图的框架坐标转换为窗口的基本坐标convertRect:self.frame toView:nil)。

问题是在显示弹出框之前不会创建窗口。在此之前,无法找到视图的屏幕坐标,因为它不在屏幕上。

如果等待显示为时已晚,请捕获popoverWillShow:委​​托方法(或相应的通知),当窗口已经创建和定位时,它会在显示弹出框之前立即触发。

于 2014-01-24T06:51:22.657 回答
1

以下代码假设您有

  • 管理弹出视图的 NSViewController 子类
  • 视图控制器实现NSPopoverDelegate

正如 hamstergene 指出的那样,弹出窗口的窗口在显示之前将不可用。
popoverWillShow:委托方法被调用时,您的弹出视图的窗口应该是_NSPopoverWindow(而不是nil)的实例。

- (void)popoverWillShow:(NSNotification *)notification
{
    NSWindow* popOverWindow = self.view.window;
    NSRect popoverRectInScreenCoords = [popOverWindow convertRectToScreen:self.view.frame];
    NSLog(@"Popover Rect in Screen Coords:%@", NSStringFromRect(popoverRectInScreenCoords));
}

更新
Bryan(OP)在评论中发布了他的问题的解决方案。
问题不在于NSPopover它本身。nil他的一些子视图的窗口的实际原因是NSTableView,它释放了 non-visible NSTableCellViews
作为一种解决方法,他viewDidMoveToWindow在他的自定义NSTableCellView子类中实现了。当viewDidMoveToWindow:被调用时,表格单元格视图已经有一个可用于执行坐标转换的窗口。

于 2014-01-24T13:44:33.950 回答