Macos Mac OS X:在NSView坐标和全局屏幕坐标之间转换
我的多监视器设置中存在以下情况: 在本例中,我希望将窗口精确定位在黄色箭头所示的坐标处。然而,我所拥有的只是NSView的坐标,NSView是NSWindow的contentView的子视图,它跨越了整个(更大、更高的)二级监视器 以下是全局坐标空间的定义方式:Macos Mac OS X:在NSView坐标和全局屏幕坐标之间转换,macos,core-graphics,coordinate-systems,coordinate-transformation,Macos,Core Graphics,Coordinate Systems,Coordinate Transformation,我的多监视器设置中存在以下情况: 在本例中,我希望将窗口精确定位在黄色箭头所示的坐标处。然而,我所拥有的只是NSView的坐标,NSView是NSWindow的contentView的子视图,它跨越了整个(更大、更高的)二级监视器 以下是全局坐标空间的定义方式: {0,0}是我笔记本电脑屏幕左上角的坐标。(绿色) {-296,-1080}是第二个屏幕左上角的坐标(黑色) {0,800}是左下角的坐标(这里没有箭头) 因此,y从绿色箭头向下增加,从绿色箭头向上减少 问题: 如何将黄色箭头所示
- {0,0}是我笔记本电脑屏幕左上角的坐标。(绿色)
- {-296,-1080}是第二个屏幕左上角的坐标(黑色)
- {0,800}是左下角的坐标(这里没有箭头)
(不确定是否相关,但底部屏幕有视网膜分辨率显示。)Mac OS在不同的位置使用不同的坐标系。视图可以定义y轴是向上还是向下(
isfliped
)。窗口的原点以y轴向上的“屏幕坐标”表示。屏幕使用全局坐标系排列,y指向下方
最好不要尝试自己对所有坐标空间进行转换,而是让负责的对象进行转换:
NSView *yellowView; // your view that contains the point with the yellow arrow.
NSPoint yellowPoint = { 100, 100 };
NSPoint pointInWindow = [yellowView convertPoint:yellowPoint toView:nil];
NSPoint pointOnScreen = [[yellowView window] convertRectToScreen:(CGRect){.origin=pointInWindow}];
NSWindow *newWindow = [[NSWindow alloc] initWithContentRect:(CGRect){ pointOnScreen, {32, 32}} styleMask: ...];
公认答案的Swift(4.0)版本基本相同:
let yellowView: NSView // your view that contains the point with the yellow arrow.
let yellowPoint = NSPoint(x: 100, y: 100)
let pointInWindow = yellowView.convert(yellowPoint, to: nil)
let pointOnScreen = yellowView.window?.convertToScreen(NSRect(origin: pointInWindow, size: .zero)).origin ?? .zero
let contentRect = NSRect(origin: pointOnScreen, size: NSSize(width: 32, height: 32))
let newWindow = NSWindow(contentRect: contentRect, styleMask: ...)
以下是另一种方法:
let someView: NSView // Some existing view
var rect: NSRect
rect = NSRect(x: 100, y: 100, width: 0, height: 0)
rect = someView.convert(rect, to: nil)
rect = someView.window?.convertToScreen(rect) ?? rect
rect.size = NSSize(width: 32, height: 32)
let newWindow = NSWindow(contentRect: rect, styleMask: ...)
后一种方法只是提前设置rect。下面是为喜欢演练的人准备的一个剧本:
1。创建一个矩形。在视图坐标系中的所需位置初始化一个零尺寸的矩形
let someView: NSView // Some existing view
var rect = NSRect(x: 100, y: 100, width: 0, height: 0)
2。从视图转换为窗口。通过为目标视图指定nil
,将矩形从视图坐标系转换为窗口坐标系
rect = someView.convert(rect, to: nil)
3。从窗口转换为屏幕。接下来,将矩形从窗口坐标系转换为屏幕坐标系
请注意,someView.window
可能是nil
,因此我们使用可选链接(即window?
中的?
),如果是这种情况,则返回到rect
的原始值。这可能没有必要,但这是一个好习惯
rect = someView.window?.convertToScreen(rect) ?? rect
4。设置矩形的大小。使用新窗口的所需大小更新矩形
rect.size = NSSize(width: 32, height: 32)
5。创建窗口。使用转换后的矩形初始化新窗口
let newWindow = NSWindow(contentRect: rect, styleMask: ...)
我认为这行:nspointpointonscreen=[[yellowView窗口]convertRectToScreen:(CGRect){.origin=pointInWindow}]代码>应该是:nspointpointonscreen=[[yellowView窗口]convertRectToScreen:(CGRect){.origin=pointInWindow}]。origin代码>