NSView inside an NSPopover: Converting Coordinates

别说谁变了你拦得住时间么 提交于 2019-12-24 16:30:02

问题


Context

Let P be an NSPopover and view be an NSView that is a subview contained within P.

What I Need

I want to take the frame of view and convert it to the screen's coordinate system. Normally, you would do that like this:

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

However, because view is in an NSPopover, its window property is nil and the above method will return NSZeroRect: [0, 0, 0, 0]

So, how can I get my view's frame in screen coordinates if the view is in an NSPopover?

Notes:

  1. The NSPopover IS onscreen and visible.
  2. The view whose frame I am trying to convert to screen coordinates is not a direct subview of the NSPopover or its contentView. The view in question is actually a custom NSView within an NSTableCellView within an NSTableView within an NSScrollView within an NSClipView. The clipView is a direct subview of the NSPopover's contentView.
  3. In a normal NSWindow, you can take any subview and call [self window] to get the containing NSWindow object. Doing that in a popover, however, returns nil.

回答1:


The following code assumes, that you have

  • a NSViewController subclass that manages the popover view
  • the view controller implements NSPopoverDelegate

As hamstergene pointed out, the popover's window won't be available until it is shown.
When the popoverWillShow: delegate method gets called, your popover view's window should be an instance of _NSPopoverWindow (and not 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));
}

Update
Bryan (the OP) posted a solution to his problem in the comments.
The issue wasn't NSPopover itself. The actual reason for the nil window for some of his subviews was NSTableView, which releases non-visible NSTableCellViews.
As a workaround he implemented viewDidMoveToWindow in his custom NSTableCellView subclass. When viewDidMoveToWindow: gets called, the table cell view already has a window that can be used to perform coordinate conversion.




回答2:


Your approach for calculating screen coordinates is correct (just don't forget to convert view's frame coordinates to window's base coordinates first using convertRect:self.frame toView:nil).

The problem is that the window is not created until the popover is displayed. Before that, there is no way to find the view's screen coordinates, because it is not on a screen.

If waiting for display is too late for you, catch popoverWillShow: delegate method (or the corresponding notification), which fires right before displaying the popover when the window is already created and positioned.



来源:https://stackoverflow.com/questions/21325479/nsview-inside-an-nspopover-converting-coordinates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!