【问题标题】:How to add NSMenu Programmatically?如何以编程方式添加 NSMenu?
【发布时间】:2015-05-01 03:54:35
【问题描述】:

我没有使用 storyboard 和 xib,只使用了代码。 我想以编程方式添加“编辑”菜单。我的问题是

1)如何显示“编辑”菜单/评论问题1)需要输入什么代码?

2) swift 提供了任何操作,例如复制和粘贴?

class TestManager: NSObject {

// ....
    override init() {
        let editMenuItems = [
            NSMenuItem(title: "Cut", action: nil(/* Question 2) */), keyEquivalent: ""),
            NSMenuItem(title: "Copy", action: nil, keyEquivalent: ""),
            NSMenuItem(title: "Paste", action: nil, keyEquivalent: ""),
        ]

        for editMenuItem in editMenuItems {
            self.editMenu.addItem(editMenuItem)
        }

        // Qustion 1) .. show "Edit" Menu
    }
}

【问题讨论】:

  • 如果您确实需要,请您说明为什么要制作一个没有主菜单的应用程序?
  • 我使用自定义代码的原因是1)我想做的类似于github.com/devxoul/allkdic(自定义代码)2)如果您知道如何编写用户界面,那么您就会知道会发生什么在引擎盖下,而对于 NIB 和 Storyboard 则不一定如此。
  • 老实说,这根本没有任何意义。如果你需要一个菜单​​(并且你声明你确实需要它),那么使用 MainMenu 作为放置在 Info.plist 中。
  • 我不太了解所有的负面因素。这是一个完全合理的问题,我也想知道答案。我想插入和附加项目。即不是静态的而是动态的。这适用于从动态菜单下载和启动应用程序的启动器应用程序。

标签: macos swift nsmenu nsmenuitem


【解决方案1】:

你没有显示self.editMenu来自哪里。

在任何情况下,您都需要从NSApplication 实例中获取mainMenu 并将一个菜单项添加到将您的菜单作为其子菜单的菜单项。所以,像:

var editMenuItem = NSMenuItem()
editMenuItem.title = "Edit"
var mainMenu = NSMenu()
mainMenu.addItem(editMenuItem)
mainMenu.setSubmenu(self.editMenu, forItem:editMenuItem)
NSApplication.sharedApplication().mainMenu = mainMenu

我不是用 Swift 工作的,所以里面可能有一些错误。

至于编辑菜单项使用什么动作选择器,最简单的方法是创建一个主菜单NIB 来检查它。查看用于现成编辑菜单的菜单项的操作选择器。例如,您会发现 Copy 项使用 copy: 选择器。这可以在 Swift 中表示为一个字符串,"copy:"

【讨论】:

  • 感谢您的回答。我没有足够的声望。我会尝试这样做并再次发表评论。谢谢你,肯。
  • 我确实喜欢这个,gist.github.com/AstinCHOI/9791f4b0ab941a2be6da。但它没有用。感谢您的帮助。
  • 您遗漏了mainMenu?.addItem(editMenuItem) 声明。
  • 当前的要点已将其注释掉。另外,检查mainMenu 不是nil
  • 如你所料,mainMenu 为 nil T.T
【解决方案2】:

https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/MenuList/Articles/EnablingMenuItems.html

自动菜单启用

  • 如果菜单项的目标未设置(也就是说,如果它为 nil,通常如果菜单项连接到 First Responder)并且 NSMenu 对象不是上下文菜单,然后 NSMenu 使用响应者链(在响应者链中描述)来确定目标。如果在响应者链中没有没有对象来实现该项目的操作,则该项目被禁用。 如果在响应者链中有一个对象实现了项目的动作,NSMenu 然后检查该对象是否实现了validateMenuItem:validateUserInterfaceItem: 方法。如果它没有,则菜单项启用。如果是,则菜单项的启用状态由方法的返回值确定。

因此,为了实现标准系统菜单项的自动菜单启用,我们必须指定正确的action而不设置target

let menu = NSMenu(...)
menu.addItem(withTitle: "Quit \(applicationName)",
             action: #selector(NSApplication.terminate(_:)), keyEquivalent: "q")
menu.addItem(withTitle: "Select All",
             action: #selector(NSText.selectAll(_:)), keyEquivalent: "a")
menu.addItem(withTitle: "Copy",
             action: #selector(NSText.copy(_:)), keyEquivalent: "c")

【讨论】:

    【解决方案3】:

    我发现这里的答案大体上是正确的,但缺少一些东西,所以我将添加我的完整解决方案。就我而言,我只想添加一个“调试”菜单用于开发。

    func addDebugMenu() {
        let debugMenu = NSMenuItem(title: "Debug", action: nil, keyEquivalent: "")
        debugMenu.submenu = NSMenu(title: "Debug")
        debugMenu.submenu?.addItem(withTitle: "Load saved data", action: #selector(self.loadDataFromFile(_:)), keyEquivalent: "")
        NSApplication.shared.mainMenu?.addItem(debugMenu)
    }
    
    @objc func loadDataFromFile(_ sender: Any) {
        print("load it")
    }
    

    对于完整的解决方案,仅在开发时这样称呼它:

    #if DEBUG
    addDebugMenu()
    #endif
    

    我的环境是:Xcode 12.3、macOS 10.15.7、Swift 5.3.2

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-03-02
      • 1970-01-01
      • 1970-01-01
      • 2015-08-17
      • 2016-11-23
      • 2012-09-16
      • 2014-07-03
      • 2016-04-02
      相关资源
      最近更新 更多