问题描述
我有以下代码:(可以复制粘贴到新的MacOS项目)
import Cocoa
import SwiftUI
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBarItem: NSStatusItem!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let statusBar = NSStatusBar.system
statusBarItem = statusBar.statusItem(
withLength: NSStatusItem.squareLength)
statusBarItem.button?.title = ""
// Setting action
statusBarItem.button?.action = #selector(self.statusBarButtonClicked(sender:))
statusBarItem.button?.sendAction(on: [.leftMouseUp])
let statusBarMenu = NSMenu(title: "Status Bar Menu")
statusBarMenu.addItem(
withTitle: "Order an apple",
action: #selector(AppDelegate.orderAnApple),
keyEquivalent: "")
statusBarMenu.addItem(
withTitle: "Cancel apple order",
action: #selector(AppDelegate.cancelAppleOrder),
keyEquivalent: "")
// Setting menu
statusBarItem.menu = statusBarMenu
}
@objc func statusBarButtonClicked(sender: NSStatusBarButton) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp {
print("Right click!")
} else {
print("Left click!")
}
}
@objc func orderAnApple() {
print("Ordering a apple!")
}
@objc func cancelAppleOrder() {
print("Canceling your order :(")
}
}
删除此行后:
statusBarItem.menu = statusBarMenu
所需行为:右击菜单打开,左击菜单未打开,操作被触发。如何实现?
编辑
我在@red_menace评论的帮助下成功实现了预期的行为:
import Cocoa
import SwiftUI
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
var statusBarItem: NSStatusItem!
var menu: NSMenu!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let statusBar = NSStatusBar.system
statusBarItem = statusBar.statusItem(
withLength: NSStatusItem.squareLength)
statusBarItem.button?.title = ""
// Setting action
statusBarItem.button?.action = #selector(self.statusBarButtonClicked(sender:))
statusBarItem.button?.sendAction(on: [.leftMouseUp, .rightMouseUp])
let statusBarMenu = NSMenu(title: "Status Bar Menu")
statusBarMenu.addItem(
withTitle: "Order an apple",
action: #selector(AppDelegate.orderAnApple),
keyEquivalent: "")
statusBarMenu.addItem(
withTitle: "Cancel apple order",
action: #selector(AppDelegate.cancelAppleOrder),
keyEquivalent: "")
// Setting menu
menu = statusBarMenu
}
@objc func statusBarButtonClicked(sender: NSStatusBarButton) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp {
statusBarItem.popUpMenu(menu)
} else {
print("Left click!")
}
}
@objc func orderAnApple() {
print("Ordering a apple!")
}
@objc func cancelAppleOrder() {
print("Canceling your order :(")
}
}
有没有办法通过新的API实现所需的行为?
推荐答案
显示菜单的通常方式是将菜单分配给状态项,在单击状态项按钮时将在其中显示该菜单。由于popUpMenu
已弃用,因此需要另一种方式来显示不同条件下的菜单。如果希望右击使用实际的状态项菜单,而不是仅在状态项位置显示上下文菜单,则状态项菜单属性可以保持为空,直到您想要显示它。
我对您的代码进行了修改,使statusBarItem
和statusBarMenu
引用保持分离,仅将菜单添加到单击的操作方法中的状态项。在操作方法中,一旦添加了菜单,就会在状态按钮上执行正常的单击以删除菜单。由于在单击按钮时状态项将始终显示其菜单,因此添加了NSMenuDelegate方法,以便在菜单关闭时将Menu属性设置为nil
,从而恢复原始操作:
import Cocoa
@NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate, NSMenuDelegate {
// keep status item and menu separate
var statusBarItem: NSStatusItem!
var statusBarMenu: NSMenu!
func applicationDidFinishLaunching(_ aNotification: Notification) {
let statusBar = NSStatusBar.system
statusBarItem = statusBar.statusItem(withLength: NSStatusItem.squareLength)
statusBarItem.button?.title = ""
statusBarItem.button?.action = #selector(self.statusBarButtonClicked(sender:))
statusBarItem.button?.sendAction(on: [.leftMouseUp, .rightMouseUp])
statusBarMenu = NSMenu(title: "Status Bar Menu")
statusBarMenu.delegate = self
statusBarMenu.addItem(
withTitle: "Order an apple",
action: #selector(AppDelegate.orderAnApple),
keyEquivalent: "")
statusBarMenu.addItem(
withTitle: "Cancel apple order",
action: #selector(AppDelegate.cancelAppleOrder),
keyEquivalent: "")
}
@objc func statusBarButtonClicked(sender: NSStatusBarButton) {
let event = NSApp.currentEvent!
if event.type == NSEvent.EventType.rightMouseUp {
print("Right click!")
statusBarItem.menu = statusBarMenu // add menu to button...
statusBarItem.button?.performClick(nil) // ...and click
} else {
print("Left click!")
}
}
@objc func menuDidClose(_ menu: NSMenu) {
statusBarItem.menu = nil // remove menu so button works as before
}
@objc func orderAnApple() {
print("Ordering a apple!")
}
@objc func cancelAppleOrder() {
print("Canceling your order :(")
}
}