NSPopover应用程序并不总是出现在应有的位置

时间:2017-09-19 12:08:58

标签: cocoa appkit nspopover

我正在开发NSPopover应用程序。我使用raywenderlich tutorial作为起点。

我遇到的问题是,当弹出窗口打开并且系统状态栏关闭时(例如在笔记本电脑上使用多个全屏应用程序时),弹出窗口显示在屏幕的左下角。

有没有办法强制系统状态栏在弹出窗口打开时打开并保持打开状态?

2 个答案:

答案 0 :(得分:2)

我们遇到了类似的问题,并最终检测到系统菜单栏何时被最小化:

[NSMenu menuBarVisible]

至于保持窗口可见,您可以使用NSBorderlessWindowMask | NSNonactivatingPanelMask

动态分享您的窗口样式

答案 1 :(得分:0)

问题是,当状态栏不可见时,statusItem /按钮的位置很奇怪,因此它位于屏幕的左侧。

对此的一种可能的解决方案是在首次打开弹出窗口时保存位置,并相对于该点继续显示它。在此answer中,他们将弹出窗口相对于不可见窗口放置。我们之所以需要这样做是因为,当我们显示相对于statusItem /按钮的弹出框时,如果状态不可见,则该位置很奇怪。

因此,如果将窗口另存为变量并显示相对于此的弹出式窗口,则最终会得到如下所示:

static let popover = NSPopover()
var invisibleWindow: NSWindow!

func showPopover(sender: Any?) {
    if let button = AppDelegate.statusItem.button {
        if (invisibleWindow == nil) {
            invisibleWindow = NSWindow(contentRect: NSMakeRect(0, 0, 20, 1), styleMask: .borderless, backing: .buffered, defer: false)
            invisibleWindow.backgroundColor = .red
            invisibleWindow.alphaValue = 0

            // find the coordinates of the statusBarItem in screen space
            let buttonRect:NSRect = button.convert(button.bounds, to: nil)
            let screenRect:NSRect = button.window!.convertToScreen(buttonRect)

            // calculate the bottom center position (10 is the half of the window width)
            let posX = screenRect.origin.x + (screenRect.width / 2) - 10
            let posY = screenRect.origin.y

            // position and show the window
            invisibleWindow.setFrameOrigin(NSPoint(x: posX, y: posY))
            invisibleWindow.makeKeyAndOrderFront(self)
        }

        AppDelegate.popover.show(relativeTo: invisibleWindow.contentView!.frame, of: invisibleWindow.contentView!, preferredEdge: NSRectEdge.minY)
        NSApp.activate(ignoringOtherApps: true)
    }
}