Cocoa:右键单击NSTableView的单元格时如何设置上下文菜单

Nat*_*n H 15 cocoa contextmenu nstableview

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

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

- (NSMenu *)menuForEvent:(NSEvent *)theEvent;
Run Code Online (Sandbox Code Playgroud)

但它永远不会被召唤.

另一方面,

- (void)rightMouseDown:(NSEvent *)theEvent;
Run Code Online (Sandbox Code Playgroud)

获取调用.但我不确定这是我们想要的那个.

更多细节:

//
//  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
Run Code Online (Sandbox Code Playgroud)

rightMouseDown被调用.hiTest被多次调用.但是menuForEvent没有.

Rob*_*ger 60

无需处理事件处理,只需指定上下文菜单,就可以将表视图的menu出口设置为指向NSMenu要用于上下文菜单的对象.

您可以在Interface Builder中执行此操作,方法是将NSMenu对象放入nib文件并从表视图控制拖动到菜单以设置插座.

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

  • 对于任何绊到这个的人,你会得到与`tableView.clickedRow`相关联的行 (11认同)
  • @ErikAigner可以使用NSMenu委托方法(特别是menu(NSMenu,update:NSMenuItem,at:Int,shouldCancel:Bool)`)来隐藏与菜单显示无关的菜单项。 (2认同)

Leo*_*eon 8

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
Run Code Online (Sandbox Code Playgroud)

功能:

@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()
}
Run Code Online (Sandbox Code Playgroud)