Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/macos/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Macos Mac OS X:在NSView坐标和全局屏幕坐标之间转换_Macos_Core Graphics_Coordinate Systems_Coordinate Transformation - Fatal编程技术网

Macos Mac OS X:在NSView坐标和全局屏幕坐标之间转换

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从绿色箭头向下增加,从绿色箭头向上减少 问题: 如何将黄色箭头所示

我的多监视器设置中存在以下情况:

在本例中,我希望将窗口精确定位在黄色箭头所示的坐标处。然而,我所拥有的只是NSView的坐标,NSView是NSWindow的contentView的子视图,它跨越了整个(更大、更高的)二级监视器

以下是全局坐标空间的定义方式:

  • {0,0}是我笔记本电脑屏幕左上角的坐标。(绿色)
  • {-296,-1080}是第二个屏幕左上角的坐标(黑色)
  • {0,800}是左下角的坐标(这里没有箭头)
因此,y从绿色箭头向下增加,从绿色箭头向上减少

问题:

如何将黄色箭头所示的点({100100},NSView位于此NSScreen内的NSWindow内)转换为全局坐标系。(注意:在NSView中,坐标系左下角有{0,0},向上递增。)

我相信正确的答案是{-196,-980},但是对于任何屏幕上的任何窗口,获得这种转换的代码是什么

我已经在这个问题上花费了太多的时间,所以非常感谢您的帮助


(不确定是否相关,但底部屏幕有视网膜分辨率显示。)

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