【问题标题】:Cocoa: How to have a context menu when you right-click on a cell of NSTableViewCocoa:右键单击 NSTableView 的单元格时如何拥有上下文菜单
【发布时间】:2011-05-31 11:36:53
【问题描述】:

我有一个带有自定义单元格的 TableView。我希望当用户在其中一个单元格上单击鼠标右键(或任何其他 Apple 右键单击​​变体)时出现上下文菜单(并知道他们单击了哪个单元格)。

我尝试继承 NSTableView 并覆盖此方法:

- (NSMenu *)menuForEvent:(NSEvent *)theEvent;

但它永远不会被调用。

另一方面,

- (void)rightMouseDown:(NSEvent *)theEvent;

被调用。但我不确定它是否是我们想要的。

更多细节:

//
//  PTTableView.m
// 
//
//  Created by Nathan Hazout on 5/31/11.
//  Copyright 2011 __MyCompanyName__. All rights reserved.
//

#import "PTTableView.h"


@implementation PTTableView

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

- (void)rightMouseDown:(NSEvent *)theEvent { 
    NSLog(@"entered rightMouseDown");
}

- (NSMenu *)menuForEvent:(NSEvent *)theEvent {
    NSLog(@"entered menuForEvent");
    return [super menuForEvent:theEvent];
}

- (NSView *)hitTest:(NSPoint)aPoint{
    NSLog(@"entered hitTest");
    return [super hitTest:aPoint];
}

- (void)dealloc
{
    [super dealloc];
}

@end

rightMouseDown 被调用。 hiTest 被多次调用。但 menuForEvent 没有。

【问题讨论】:

    标签: cocoa contextmenu nstableview


    【解决方案1】:

    没有必要为事件处理而烦恼,分配上下文菜单所需要做的就是将表格视图的menu 出口设置为指向要用于上下文菜单的NSMenu 对象。

    您可以在 Interface Builder 中执行此操作,方法是将 NSMenu 对象拖放到您的 nib 文件中,然后从表格视图控制拖动到菜单以设置出口。

    或者,您可以使用NSTableView(继承自NSResponder)的-setMenu: 方法以编程方式分配菜单。

    【讨论】:

    • 我应该在 TableView 还是 Cell 上做?
    • 您将上下文菜单分配给视图。
    • 对于遇到此问题的任何人,您将获得与 tableView.clickedRow 相关联的行
    • @ErikAigner 这就是菜单验证委托方法的用途。
    • @ErikAigner 可以使用NSMenu 委托方法(特别是menu(NSMenu, update: NSMenuItem, at: Int, shouldCancel: Bool))在菜单显示之前隐藏不相关的菜单项。
    【解决方案2】:

    Rob 答案的 Swift 4 版本:

    添加菜单:

    let menu = NSMenu()
    menu.addItem(NSMenuItem(title: "Edit", action: #selector(tableViewEditItemClicked(_:)), keyEquivalent: ""))
    menu.addItem(NSMenuItem(title: "Delete", action: #selector(tableViewDeleteItemClicked(_:)), keyEquivalent: ""))
    tableView.menu = menu
    

    功能:

    @objc private func tableViewEditItemClicked(_ sender: AnyObject) {
    
        guard tableView.clickedRow >= 0 else { return }
    
        let item = items[tableView.clickedRow]
    
        showDetailsViewController(with: item)
    }
    
    @objc private func tableViewDeleteItemClicked(_ sender: AnyObject) {
    
        guard tableView.clickedRow >= 0 else { return }
    
        items.remove(at: tableView.clickedRow)
    
        tableView.reloadData()
    }
    

    【讨论】:

    • 此解决方案在单元格周围创建蓝色边框
    • @Sentry.co 我不确定为什么这个解决方案会这样做,因为它没有样式属性。
    • 什么是showDetailsViewController方法?
    • @iHTCboy 只是一个使用所选项目调用 DetailsVC 的方法
    猜你喜欢
    • 2010-09-21
    • 2016-02-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-15
    • 2017-04-22
    • 1970-01-01
    相关资源
    最近更新 更多