如何在 Swift 5 中以编程方式在特定屏幕(即主显示器而不是外部显示器)上显示窗口? [苹果系统; Xcode 15]

Posted

技术标签:

【中文标题】如何在 Swift 5 中以编程方式在特定屏幕(即主显示器而不是外部显示器)上显示窗口? [苹果系统; Xcode 15]【英文标题】:How can I programmatically display a window on a specific screen (i.e., main display as opposed to external displays) in Swift 5? [MacOS; Xcode 15] 【发布时间】:2022-01-11 11:51:32 【问题描述】:

我在特定屏幕上显示我的应用程序窗口时遇到了困难(即主显示器而不是我的外部显示器)。我想在主显示器上显示我的应用程序的原因是我想稍后通过使用CGDisplayCapture(CGDirectDisplayID(2)) 来清空我的外部显示器。

我找到了几个建议和实现如下。

Swift 3/macOS: Open window on certain screen

How to change the NSScreen a NSWindow appears on

Show window on multiple displays on os x

how to move NSWindow to a particular screen?

但是,我无法弄清楚如何在 Swift 5 中实现这一点。这可能是因为以前的帖子已经过时了。例如,以下我的代码(基于Swift 3/macOS: Open window on certain screen)不起作用......它什么也没做。

override func viewDidLoad() 
    super.viewDidLoad()
    
    //set up the main display as the display where window shows up
    let screens = NSScreen.screens
    var pos = NSPoint()
    pos.x = screens[0].visibleFrame.midX
    pos.y = screens[0].visibleFrame.midY
    self.view.window?.setFrameOrigin(pos)

如果我能听到如何实现这一点,我将不胜感激。

补充:

提供给Cocoa show NSWindow on a specific screen 的答案似乎是用objective-c 编写的。不幸的是,我不懂objective-c。

补充:

感谢@al45tair提供的答案,我尝试在appDegate中使用windowController如下:

 func applicationDidFinishLaunching(_ aNotification: Notification) 
    // Insert code here to initialize your application
    let storyboard = NSStoryboard(name: "Main", bundle: nil)
    if let windowController = storyboard.instantiateController(withIdentifier: "mainWindow") as? NSWindowController 
        
        //keep the window top
        windowController.window?.level = .floating


        //set up the main display as the display where window shows up
        let screens = NSScreen.screens
        var pos = NSPoint()
        pos.x = screens[0].visibleFrame.midX
        pos.y = screens[0].visibleFrame.midY
        windowController.window?.setFrameOrigin(pos)


        windowController.window?.zoom(self)
        windowController.window?.level = .floating
        windowController.window?.backgroundColor = NSColor.white

        //stop the user from moving window
        windowController.window?.isMovable = false
        //disable resizable mode
        windowController.window?.styleMask.remove(.resizable)
        windowController.showWindow(self)

     else 
        print ("failed to show the window")
    
 

我还将主窗口控制器勾选为initial controller(否则,我会得到两个相同的初始窗口)。 但是,我意识到通过使用这种方法,我无法通过在ViewController.swift 中使用self.view.window?.setIsVisible(false)(或true)来隐藏和显示窗口。我做错了什么?

【问题讨论】:

self.view.window 是否返回一个窗口? 感谢您的提问!我检查并意识到self.view.window 没有返回窗口!我怎么能从这里走? 这能回答你的问题吗? Cocoa show NSWindow on a specific screen 谢谢你,@Willeke。问题是,链接问题中提供的答案似乎是用objective-c 写的,而且我不理解objective-c。我正在寻找swift 5 替代方案。 【参考方案1】:

感谢@Willeke 提出的问题,我能够使用以下代码在主屏幕上显示窗口(而不是外部显示器)。我只需要使用DispatchQueue.main.async

   override func viewDidLoad() 
         super.viewDidLoad()
         DispatchQueue.main.async 
             
             //set up the main display as the display where window shows up
             let screens = NSScreen.screens
             var pos = NSPoint()
             pos.x = screens[0].visibleFrame.midX
             pos.y = screens[0].visibleFrame.midY
             self.view.window?.setFrameOrigin(pos)
             
         
    

【讨论】:

【参考方案2】:

ViewController 不适合这样做。要么使用WindowController 并将相关代码放在windowDidLoad 中,或者,如果您真的想要一个导致其父窗口填充主显示的视图,请在您的视图上覆盖viewDidMoveToWindow。 (在大多数情况下,后者在 IMO 中会有点奇怪。)

【讨论】:

非常感谢@al45tair 的回答!作为一个初学者,我真的很感激学习这个。如果可能的话,您能否详细说明为什么我不应该在ViewController 中处理这个(self.view.window??以及相关的东西?)?如果您可以提供一个在WindowController 中实现的简单示例代码,那也会有很大帮助。我一直在寻找处理屏幕的示例代码,但我一直无法找到简单的代码以及我可以在线理解的解释。

以上是关于如何在 Swift 5 中以编程方式在特定屏幕(即主显示器而不是外部显示器)上显示窗口? [苹果系统; Xcode 15]的主要内容,如果未能解决你的问题,请参考以下文章

我可以在 Swift 5 和 IOS 12 中以编程方式更改 iOS 屏幕壁纸吗

如何在 Swift 中以编程方式更改 UIButton 状态

如何在 UIAlertController 中以编程方式更改特定按钮文本颜色

在 Swift 中以编程方式添加时,UIScrollView 根本不滚动?

获取 Button 和 Textfield 数据,当它们在 swift 5 中以编程方式添加时

UIScrollView 在 Swift 中以编程方式