上下文
令 P
为 NSPopover,view
为 NSView,它是包含在 P
中的 subview 。
我需要什么
我想获取 View
的框架并将其转换为屏幕坐标系。通常,您会这样做:
NSRect frameRelativeToWindow = [self convertRect:self.frame relativeToView:nil];
[self.window convertRectToScreen:frameRelativeToWindow];
但是,由于 view
位于 NSPopover 中,因此其 window
属性为 nil,上述方法将返回 NSZeroRect: [0, 0, 0, 0]
那么,如果 View 位于 NSPopover 中,如何在屏幕坐标中获取 View 的框架?
注释:
- NSPopover 在屏幕上可见。
- 我尝试将其框架转换为屏幕坐标的 View 不是 NSPopover 或其 contentView 的直接 subview 。所讨论的 View 实际上是 NSTableCellView 内的自定义 NSView,NSTableCellView 内的 NSTableView 内的 NSScrollView 内的 NSClipView。 ClipView 是 NSPopover 的 contentView 的直接 subview 。
- 在普通的 NSWindow 中,您可以获取任何 subview 并调用
[self window]
来获取包含的 NSWindow 对象。然而,在弹出窗口中执行此操作会返回 nil。
最佳答案
以下代码假设您有
- 管理弹出 View 的 NSViewController 子类
- View Controller 实现
NSPopoverDelegate
正如 hamstergene 指出的,弹出窗口的窗口在显示之前才可用。
当调用 popoverWillShow:
委托(delegate)方法时,弹出窗口 View 的窗口应该是 _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));
}
更新
布莱恩(OP)在评论中发布了他的问题的解决方案。
问题不在于 NSPopover
本身。他的一些 subview 的 nil
窗口的实际原因是 NSTableView
,它释放了不可见的 NSTableCellViews
。
作为一种解决方法,他在自定义的 NSTableCellView
子类中实现了 viewDidMoveToWindow
。当viewDidMoveToWindow:
被调用时,表格单元格 View 已经有一个可用于执行坐标转换的窗口。
关于macos - NSPopover 内的 NSView : Converting Coordinates,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21325479/