首页 > 其他分享 >Mac开发基础23-NSMenu

Mac开发基础23-NSMenu

时间:2024-08-06 18:05:23浏览次数:16  
标签:NSMenuItem 23 menu title NSMenu Mac menuItem 菜单项

NSMenu 是 macOS 应用中的一个重要控件,用于创建应用程序的菜单。这些菜单通常出现在屏幕顶部的菜单栏中,但也可以作为上下文菜单出现。NSMenuNSMenuItem 协同工作,NSMenu 是菜单容器,而 NSMenuItem 是菜单项。本指南将详细介绍 NSMenu 的常见 API 和基础技巧。

基本使用

创建和初始化

Objective-C

#import <Cocoa/Cocoa.h>

// 创建一个 NSMenu 实例
NSMenu *menu = [[NSMenu alloc] initWithTitle:@"Main Menu"];

Swift

import Cocoa

// 创建一个 NSMenu 实例
let menu = NSMenu(title: "Main Menu")

创建菜单项

Objective-C

// 创建菜单项
NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:@"First Item"
                                                  action:@selector(handleMenuAction:)
                                           keyEquivalent:@"1"];
// 设置菜单项的目标对象
[menuItem setTarget:self];

// 将菜单项添加到菜单
[menu addItem:menuItem];

Swift

// 创建菜单项
let menuItem = NSMenuItem(title: "First Item",
                          action: #selector(handleMenuAction(_:)),
                          keyEquivalent: "1")
// 设置菜单项的目标对象
menuItem.target = self

// 将菜单项添加到菜单
menu.addItem(menuItem)

响应菜单项选择

Objective-C

// 实现菜单项选择的响应方法
- (void)handleMenuAction:(id)sender {
    NSMenuItem *selectedItem = (NSMenuItem *)sender;
    NSLog(@"Selected item: %@", selectedItem.title);
}

Swift

// 实现菜单项选择的响应方法
@objc func handleMenuAction(_ sender: Any?) {
    if let menuItem = sender as? NSMenuItem {
        print("Selected item: \(menuItem.title)")
    }
}

创建带有子菜单的菜单项

Objective-C

// 创建子菜单
NSMenu *subMenu = [[NSMenu alloc] initWithTitle:@"Sub Menu"];

// 创建子菜单项
NSMenuItem *subMenuItem = [[NSMenuItem alloc] initWithTitle:@"Sub Item"
                                                     action:@selector(handleSubMenuAction:)
                                              keyEquivalent:@""];
[subMenuItem setTarget:self];
[subMenu addItem:subMenuItem];

// 创建带有子菜单的菜单项
NSMenuItem *mainMenuItem = [[NSMenuItem alloc] initWithTitle:@"Main Item"
                                                      action:NULL
                                               keyEquivalent:@""];
[menu addItem:mainMenuItem];
[menu setSubmenu:subMenu forItem:mainMenuItem];

Swift

// 创建子菜单
let subMenu = NSMenu(title: "Sub Menu")

// 创建子菜单项
let subMenuItem = NSMenuItem(title: "Sub Item", action: #selector(handleSubMenuAction(_:)), keyEquivalent: "")
subMenuItem.target = self
subMenu.addItem(subMenuItem)

// 创建带有子菜单的菜单项
let mainMenuItem = NSMenuItem(title: "Main Item", action: nil, keyEquivalent: "")
menu.addItem(mainMenuItem)
menu.setSubmenu(subMenu, for: mainMenuItem)

动态更新菜单项

Objective-C

// 更新菜单项状态
- (void)updateMenuItems {
    NSMenuItem *menuItem = [menu itemWithTitle:@"First Item"];
    if (menuItem) {
        [menuItem setState:NSControlStateValueOn]; // 或者使用 NSControlStateValueOff
    }
}

Swift

// 更新菜单项状态
func updateMenuItems() {
    if let menuItem = menu.item(withTitle: "First Item") {
        menuItem.state = .on // 或者使用 .off
    }
}

使用委托

NSMenuDelegate 可以帮助处理菜单的显示和隐藏等事件。

Objective-C

// 设置代理
[menu setDelegate:self];

// 实现代理方法,处理菜单将显示事件
- (void)menuWillOpen:(NSMenu *)menu {
    NSLog(@"Menu will open");
}

// 实现代理方法,处理菜单将隐藏事件
- (void)menuDidClose:(NSMenu *)menu {
    NSLog(@"Menu did close");
}

Swift

// 设置代理
menu.delegate = self

// 实现代理方法,处理菜单将显示事件
func menuWillOpen(_ menu: NSMenu) {
    print("Menu will open")
}

// 实现代理方法,处理菜单将隐藏事件
func menuDidClose(_ menu: NSMenu) {
    print("Menu did close")
}

高级用法

动态生成菜单项

Objective-C

// 动态生成菜单项
- (void)generateDynamicMenuItems {
    NSArray *items = @[@"Dynamic Item 1", @"Dynamic Item 2", @"Dynamic Item 3"];
    for (NSString *itemTitle in items) {
        NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:itemTitle
                                                          action:@selector(handleDynamicMenuAction:)
                                                   keyEquivalent:@""];
        [menuItem setTarget:self];
        [menu addItem:menuItem];
    }
}

Swift

// 动态生成菜单项
func generateDynamicMenuItems() {
    let items = ["Dynamic Item 1", "Dynamic Item 2", "Dynamic Item 3"]
    for itemTitle in items {
        let menuItem = NSMenuItem(title: itemTitle, action: #selector(handleDynamicMenuAction(_:)), keyEquivalent: "")
        menuItem.target = self
        menu.addItem(menuItem)
    }
}

上下文菜单

创建右键上下文菜单是 NSMenu 的常见用法。

Objective-C

// 创建上下文菜单
NSMenu *contextMenu = [[NSMenu alloc] initWithTitle:@"Context Menu"];
NSMenuItem *contextMenuItem = [[NSMenuItem alloc] initWithTitle:@"Context Item"
                                                         action:@selector(handleContextMenuAction:)
                                                  keyEquivalent:@""];
[contextMenuItem setTarget:self];
[contextMenu addItem:contextMenuItem];

// 设置视图的上下文菜单
[someView setMenu:contextMenu];

Swift

// 创建上下文菜单
let contextMenu = NSMenu(title: "Context Menu")
let contextMenuItem = NSMenuItem(title: "Context Item", action: #selector(handleContextMenuAction(_:)), keyEquivalent: "")
contextMenuItem.target = self
contextMenu.addItem(contextMenuItem)

// 设置视图的上下文菜单
someView.menu = contextMenu

禁用或启用菜单项

Objective-C

// 禁用菜单项
- (void)disableMenuItem {
    NSMenuItem *menuItem = [menu itemWithTitle:@"First Item"];
    [menuItem setEnabled:NO]; // 设置菜单项为禁用状态
}

// 启用菜单项
- (void)enableMenuItem {
    NSMenuItem *menuItem = [menu itemWithTitle:@"First Item"];
    [menuItem setEnabled:YES]; // 设置菜单项为启用状态
}

Swift

// 禁用菜单项
func disableMenuItem() {
    if let menuItem = menu.item(withTitle: "First Item") {
        menuItem.isEnabled = false // 设置菜单项为禁用状态
    }
}

// 启用菜单项
func enableMenuItem() {
    if let menuItem = menu.item(withTitle: "First Item") {
        menuItem.isEnabled = true // 设置菜单项为启用状态
    }
}

自动更新菜单项状态

通过实现 NSMenuDelegatemenu:updateItem:atIndex:shouldCancel: 方法,可以自动更新菜单项状态。

Objective-C

// 设置代理
[menu setDelegate:self];

// 实现代理方法,自动更新菜单项状态
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel {
    item.state = (index % 2 == 0) ? NSControlStateValueOn : NSControlStateValueOff;
    return YES;
}

Swift

// 设置代理
menu.delegate = self

// 实现代理方法,自动更新菜单项状态
func menu(_ menu: NSMenu, update item: NSMenuItem, at index: Int, shouldCancel: Bool) -> Bool {
    item.state = (index % 2 == 0) ? .on : .off
    return true
}

封装工具类

为了更方便地使用 NSMenu,可以封装一个工具类,提供常见功能的高层接口。

Objective-C

#import <Cocoa/Cocoa.h>

@interface NSMenuHelper : NSObject

+ (NSMenu *)createMenuWithTitle:(NSString *)title items:(NSArray<NSDictionary<NSString *, NSString *> *> *)items target:(id)target;
+ (void)addItemWithTitle:(NSString *)title action:(SEL)action toMenu:(NSMenu *)menu target:(id)target;
+ (void)addSubMenuWithTitle:(NSString *)title toMenu:(NSMenu *)menu subMenu:(NSMenu *)subMenu;

@end

@implementation NSMenuHelper

+ (NSMenu *)createMenuWithTitle:(NSString *)title items:(NSArray<NSDictionary<NSString *, NSString *> *> *)items target:(id)target {
    NSMenu *menu = [[NSMenu alloc] initWithTitle:title];
    for (NSDictionary<NSString *, NSString *> *item in items) {
        NSString *title = item.allKeys.firstObject;
        SEL action = NSSelectorFromString(item.allValues.firstObject);
        [NSMenuHelper addItemWithTitle:title action:action toMenu:menu target:target];
    }
    return menu;
}

+ (void)addItemWithTitle:(NSString *)title action:(SEL)action toMenu:(NSMenu *)menu target:(id)target {
    NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:title action:action keyEquivalent:@""];
    [menuItem setTarget:target];
    [menu addItem:menuItem];
}

+ (void)addSubMenuWithTitle:(NSString *)title toMenu:(NSMenu *)menu subMenu:(NSMenu *)subMenu {
    NSMenuItem *menuItem = [[NSMenuItem alloc] initWithTitle:title action:nil keyEquivalent:@""];
    [menu addItem:menuItem];
    [menu setSubmenu:subMenu forItem:menuItem];
}

@end

Swift

import Cocoa

class NSMenuHelper {
    
    // 创建 Menu 并初始化菜单项
    static func createMenu(title: String, items: [String: Selector], target: AnyObject) -> NSMenu {
        let menu = NSMenu(title: title)
        for (title, action) in items {
            addItem(withTitle: title, action: action, to: menu, target: target)
        }
        return menu
    }
    
    // 添加菜单项
    static func addItem(withTitle title: String, action: Selector, to menu: NSMenu, target: AnyObject) {
        let menuItem = NSMenuItem(title: title, action: action, keyEquivalent: "")
        menuItem.target = target
        menu.addItem(menuItem)
    }
    
    // 添加子菜单
    static func addSubMenu(withTitle title: String, to menu: NSMenu, subMenu: NSMenu) {
        let menuItem = NSMenuItem(title: title, action: nil, keyEquivalent: "")
        menu.addItem(menuItem)
        menu.setSubmenu(subMenu, for: menuItem)
    }
}

使用示例

Objective-C

// 创建 Menu
NSArray *items = @[
    @{@"First Item": NSStringFromSelector(@selector(handleMenuAction:))},
    @{@"Second Item": NSStringFromSelector(@selector(handleMenuAction:))}
];
NSMenu *menu = [NSMenuHelper createMenuWithTitle:@"Main Menu" items:items target:self];

// 创建子菜单
NSMenu *subMenu = [NSMenuHelper createMenuWithTitle:@"Sub Menu" items:@{@{@"Sub Item": NSStringFromSelector(@selector(handleSubMenuAction:))}} target:self];
[NSMenuHelper addSubMenuWithTitle:@"Main Item with SubMenu" toMenu:menu subMenu:subMenu];

Swift

// 创建 Menu
let items: [String: Selector] = [
    "First Item": #selector(handleMenuAction(_:)),
    "Second Item": #selector(handleMenuAction(_:))
]
let menu = NSMenuHelper.createMenu(title: "Main Menu", items: items, target: self)

// 创建子菜单
let subMenuItems: [String: Selector] = [
    "Sub Item": #selector(handleSubMenuAction(_:))
]
let subMenu = NSMenuHelper.createMenu(title: "Sub Menu", items: subMenuItems, target: self)
NSMenuHelper.addSubMenu(withTitle: "Main Item with SubMenu", to: menu, subMenu: subMenu)

总结

通过了解 NSMenu 的基本使用、创建菜单项、响应菜单项选择、创建子菜单、动态更新菜单项、使用上下文菜单等高级用法,以及封装工具类,你将能够更高效地使用 NSMenu 创建复杂的菜单系统。在实际应用中,合理使用这些技巧可以显著提升用户界面的灵活性和用户体验。。

标签:NSMenuItem,23,menu,title,NSMenu,Mac,menuItem,菜单项
From: https://www.cnblogs.com/chglog/p/18345753

相关文章

  • Mac开发基础21-NSSplitView
    NSSplitView是macOS应用中的一个重要控件,允许用户调整窗口中的各个子视图大小。它通常用于创建可调整大小的面板布局,例如侧边栏和主内容区域。在本指南中,我们将详细介绍NSSplitView的常见API和基础技巧,并深入探讨相关知识。基本使用创建和初始化Objective-C#import<Co......
  • Mac开发基础20-NSCollectionView
    NSCollectionView是macOS开发中的一种强大控件,类似于iOS上的UICollectionView,用于展示和管理网格、列表等多种布局的数据展示视图。1.基本使用创建和初始化Objective-C#import<Cocoa/Cocoa.h>//创建并初始化一个NSCollectionView实例NSCollectionView*collecti......
  • Mac开发基础19-NSTableView(二)
    进阶使用和技巧1.单击和双击行事件处理Objective-C//单击行时的处理-(void)tableView:(NSTableView*)tableViewdidClickTableColumn:(NSTableColumn*)tableColumn{NSIntegerclickedRow=[tableViewclickedRow];if(clickedRow>=0){NSLog(@"Si......
  • Mac开发基础18-NSTableView(一)
    NSTableView是macOS应用程序中用于显示和管理数据表格的控件。它提供了丰富的API和高度自定义的能力,使得开发者可以精细地控制表格的显示和行为。本文将详细介绍NSTableView的常见API和一些基础技巧,并深入探讨其相关知识。1.基本使用创建和初始化Objective-C#import......
  • LlamaCoder:一款开源的平替 Claude Artifacts 项目
    LlamaCoder是一个开源项目,旨在提供一种替代ClaudeArtifacts的解决方案。ClaudeArtifacts是一个商业软件,可能包含一些专有技术或特定的功能集,而LlamaCoder则致力于提供类似的功能,但以开源的形式,允许更广泛的社区参与和贡献。由于LlamaCoder是一个假想的开源项目,我将......
  • Mac开发基础16-NSButton(一)
    NSButton是macOS应用中常用的控件之一,用于处理各种按钮操作。它不仅提供了丰富的API来定制按钮的外观和行为,还可以通过不同的配置实现多种类型的按钮,如push按钮、toggle按钮、radio按钮等。1.基本用法创建和初始化Objective-C//创建和初始化一个NSButton实例NSB......
  • Mac开发基础17-NSButton(二)
    NSButton是一个功能强大且灵活多样的控件,除了基本使用和常见API外,还有一些进阶用法和技巧可以提高按钮的可用性和实现细节。在以下内容中,我会详细介绍一些进阶使用技巧,并封装一个常用的工具类来实现自定义的多种按钮类型。进阶使用和技巧1.自定义按钮的外观和行为Objective-C......
  • Mac开发基础13-NSTextView(一)
    NSTextView是macOS应用开发中相当强大的多行文本输入控件。它不仅支持文本输入和显示,还支持富文本、文本编辑、布局管理等功能。常见API和基础技巧初始化NSTextView程序化创建Objective-C//创建一个NSScrollView作为NSTextView的容器,因为NSTextView通常需要带滚动条的......
  • Mac开发基础14-NSTextView(二)
    进阶使用和技巧1.扩展查找和替换功能可以自定义查找和替换功能,包括高亮查找结果、批量替换等。查找并高亮Objective-C-(void)highlightOccurrencesOfString:(NSString*)searchString{//清除之前的高亮效果[textView.layoutManagerremoveTemporaryAttribute:N......
  • Xmind2024支持多平台使用,包括Windows、Mac、iOS、等操作系统
    “Xmind2024”是Xmind公司推出的一款全新的思维导图软件,它集成了多种功能,包括智能导图、AI生成、语音输入等。这款产品旨在帮助用户更高效地整理思路,提高思维能力。让我们来了解一下Xmind2024的特点。它采用了全新的设计风格,界面简洁明了,操作便捷。同时,它还提供了丰富的模板......