从 Swift 中的 NSStatusItem(菜单栏)应用程序访问菜单

Posted

技术标签:

【中文标题】从 Swift 中的 NSStatusItem(菜单栏)应用程序访问菜单【英文标题】:Menu access from NSStatusItem (Menu Bar) Application in Swift 【发布时间】:2016-01-17 16:23:55 【问题描述】:

我正在创建一个应用程序,其中菜单栏似乎是让用户的桌面在没有窗口的情况下保持清洁的最便捷方式。我在网上看过很多关于堆栈溢出的教程,但它们似乎只适用于 Objective-C。我只使用斯威夫特。如果你不知道什么是菜单栏,它们就是这些图标:

我希望我的应用程序具有其中之一,而不是恒定的完整窗口。如果可以的话,我怎么能在我的菜单栏上有一个按钮来打开窗口。最后,我怎样才能让我的图标不显示,但我仍然有取景器的优势。 (如文件,编辑..)。例如,

我已经试过了

Application is Agent (UIElement) to False

在我的 Info.plist 中,但这也剥夺了我的 finder 优势。

【问题讨论】:

"我在网上看过很多关于堆栈溢出的教程,但它们似乎只适用于 Objective-C。我只使用 Swift" 那又如何?这与语言无关。使用您找到的教程。 “Finder 优势”是什么意思? @Matt 这些教程我看不懂,因为它们是完全不同的语言。如果我想制作一个有用的应用程序,我不能编写我不理解的东西。 @rob mayoff 正在编辑。 我还是不明白“Finder 优势”是什么意思。您已经添加了 Safari 菜单栏的图片。 Safari 不是 Finder,菜单栏不是“优势”。 【参考方案1】:

您的意思大概是您希望编辑菜单中的文本编辑项(如撤消、剪切、复制、粘贴、全选)在您的应用程序窗口中工作。

这些菜单项是另一个应用程序的一部分,并且仅在该应用程序中发送消息。它们对您的应用程序不可用,无论它是否是“代理”(没有自己的可见菜单栏)。如果您的代理应用程序的一个窗口是关键窗口,并且用户单击属于另一个应用程序的菜单标题(如文件或编辑),则该应用程序将激活并且您的应用程序的窗口将“退出”关键窗口状态。

可以让常用的快捷键(例如用于 Cut 的 ⌘X)适用于您的应用,而且很简单。当您的应用程序的一个窗口是用户的关键窗口时,您的应用程序会接收键盘事件,并且您的NSApplication 对象(自动为您创建)将检查其mainMenu 的键盘快捷键,即使未显示主菜单也是如此在屏幕上

OS X“Cocoa 应用程序”项目模板在MainMenu.xib(或Main.storyboard)中为您设置了一个主菜单栏,所有菜单项都连接到相应的操作。因此,如果您保留该主菜单栏和“编辑”菜单以及“编辑”菜单中的菜单项,并保留在这些项目上设置的快捷方式,那么即使您在 @987654330 中将 LSUIElement 设置为 YES,键盘快捷方式也将起作用@,当您的应用程序的一个窗口是关键窗口时。换句话说,快捷键默认会起作用,你必须改变一些东西才能让它们停止工作。

应用程序窗口中的文本字段仍将获得默认的右键菜单,其中包含剪切、复制和粘贴等常用项目,因此您也无需执行任何其他操作即可。

这是我的测试应用MainMenu.xib的内容:

我已经单独离开了主菜单栏。我创建了一个包含两个项目的单独菜单,“显示窗口”和“退出”。我已将“退出”的快捷方式设置为 ⌘Q,但此快捷方式无效。主菜单栏外的 StatusItem > Quit 菜单项(在我的屏幕截图中不可见)具有相同的快捷方式设置,这就是重要的设置。我在另一个 Quit 项上设置了快捷方式,因为它对用户可见,而主菜单栏对用户不可见。

我已将此 Quit 项目连接到 First Responder 的 terminate: 操作。 (StatusItem > Quit 菜单项默认连接方式相同。)

这是我的AppDelegate

@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate 

    @IBOutlet var window: NSWindow!
    @IBOutlet var statusItemMenu: NSMenu!

    var statusItem: NSStatusItem?

    func applicationDidFinishLaunching(aNotification: NSNotification) 
        self.statusItem = NSStatusBar.systemStatusBar().statusItemWithLength(NSVariableStatusItemLength)
        let statusItem = self.statusItem!
        let button = statusItem.button!
        button.title = "Hello"
        statusItem.menu = statusItemMenu
    

    @IBAction func showWindow(sender: AnyObject) 
        NSApp.activateIgnoringOtherApps(true)
        window.makeKeyAndOrderFront(sender)
    


我已将“显示窗口”菜单项连接到 showWindow(_:) 操作,并将 statusItemMenu 插座连接到 XIB 中的独立菜单。

我还在Info.plist 中将“Application is Agent (UIElement)”设置为“YES”。

当我运行这个应用程序时,它会在菜单栏中创建状态项。我可以从项目中选择“显示窗口”,我的窗口来到前面并成为关键。我可以右键单击文本字段以获取其上下文菜单。我可以使用标准的快捷键来剪切/复制/粘贴/等等,关闭窗口,甚至退出应用程序。

【讨论】:

谢谢!我的应用程序没有 MainMenu.xib 文件,但在 Main.Storyboard 中有它。有没有办法可以转移它,因为我希望我的工作更干净。另外,我怎样才能用图像替换“你好”?再次,谢谢,谢谢,谢谢! 查看this tutorial。

以上是关于从 Swift 中的 NSStatusItem(菜单栏)应用程序访问菜单的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Firebreath NPAPI 插件中将 NSMenu 连接到 NSStatusItem,以便在单击状态栏项时出现菜单?

从 ViewController 访问 AppDelegate 中的对象

NSStatusItem 中的 NSProgressIndicator

使用 NSStatusItem 拖放

如何使用 NSStatusItem 作为拖动目的地?

检查 NSStatusItem 当前是不是显示在 OS X NSStatusBar 主菜单栏中