我想在NSTableView上放置一个上下文菜单。这部分已经完成了。我想做的是根据右击单元格的内容显示不同的菜单项,而不显示特定列的上下文菜单。
这是:
第0列和第1列没有上下文菜单
所有其他单元格都应具有如下所示的上下文菜单:
第一个条目:"delete“samerow.column n1.value
第二个条目:“保存”samecolumn.headertext
-编辑-
右边的是任何给定单元格的上下文菜单的外观。

发布于 2013-03-07 04:39:31
这有一个委托!-不需要子类
在IB中,如果您将一个NSTableView拖到您的窗口/视图上,您会注意到该表有一个menu插座。
因此,实现上下文菜单的一种非常简单的方法是将该出口连接到存根菜单,并将菜单的代理出口连接到实现NSMenuDelegate协议方法- (void)menuNeedsUpdate:(NSMenu *)menu的对象

通常,菜单的委托是为表提供数据源/委托的同一对象,但它也可能是拥有表的视图控制器。
有关这方面的详细信息,请访问Have a look at the docs
在这个协议中有一大堆聪明的东西可以做,但是一个非常简单的实现可能如下所示
#pragma mark tableview menu delegates
- (void)menuNeedsUpdate:(NSMenu *)menu
{
NSInteger clickedrow = [mytable clickedRow];
NSInteger clickedcol = [mytable clickedColumn];
if (clickedrow > -1 && clickedcol > -1) {
//construct a menu based on column and row
NSMenu *newmenu = [self constructMenuForRow:clickedrow andColumn:clickedcol];
//strip all the existing stuff
[menu removeAllItems];
//then repopulate with the menu that you just created
NSArray *itemarr = [NSArray arrayWithArray:[newmenu itemArray]];
for(NSMenuItem *item in itemarr)
{
[newmenu removeItem:[item retain]];
[menu addItem:item];
[item release];
}
}
}然后是一种构造菜单的方法。
-(NSMenu *)constructMenuForRow:(int)row andColumn:(int)col
{
NSMenu *contextMenu = [[[NSMenu alloc] initWithTitle:@"Context"] autorelease];
NSString *title1 = [NSString stringWithFormat:@"Delete %@",[self titleForRow:row]];
NSMenuItem *item1 = [[[NSMenuItem alloc] initWithTitle:title1 action:@selector(deleteObject:) keyEquivalent:@""] autorelease];
[contextMenu addItem:item1];
//
NSString *title2 = [NSString stringWithFormat:@"Save %@",[self titleForColumn:col]];
NSMenuItem *item2 = [[[NSMenuItem alloc] initWithTitle:title1 action:@selector(saveObject:) keyEquivalent:@""] autorelease];
[contextMenu addItem:item2];
return contextMenu;
}如何选择实现titleForRow:和titleForColumn:由您决定。
请注意,NSMenuItem提供了属性representedObject,允许您将任意对象绑定到菜单项,从而将信息发送到您的方法中(例如deleteObject:)
编辑
注意-在您的NSDocument子类中实现- (void)menuNeedsUpdate:(NSMenu *)menu将停止在10.8中出现在标题栏中的Autosave/Versions菜单。
它在10.7中仍然有效,所以去想一想吧。在任何情况下,菜单委托都需要不是您的NSDocument子类。
发布于 2013-03-06 15:18:45
编辑:比下面的方法更好的方法是使用委托,如接受的答案所示。
你可以继承你的UITableView并实现menuForEvent:方法:
-(NSMenu *)menuForEvent:(NSEvent *)event{
if (event.type==NSRightMouseDown) {
if (self.selectedColumn == 0 || self.selectedColumn ==1) {
return nil;
}else {
//create NSMenu programmatically or get a IBOutlet from one created in IB
NSMenu *menu=[[NSMenu alloc] initWithTitle:@"Custom"];
//code to set the menu items
//Instead of the following line get the value from your datasource array/dictionary
//I used this as I don't know how you have implemented your datasource, but this will also work
NSString *deleteValue = [[self preparedCellAtColumn:1 row:self.selectedRow] title];
NSString *deleteString = [NSString stringWithFormat:@"Delete %@",deleteValue];
NSMenuItem *deleteItem = [[NSMenuItem alloc] initWithTitle:deleteString action:@selector(deleteAction:) keyEquivalent:@""];
[menu addItem:deleteItem];
//save item
//similarly
[menu addItem:saveItem];
return menu;
}
}
return nil;
}这应该就行了。不过,我还没有尝试过代码。但这应该会给你一个想法。
发布于 2014-01-08 15:59:30
我也尝试了Warren Burton发布的解决方案,它工作得很好。但在我的示例中,我必须将以下内容添加到菜单项中:
[item1 setTarget:self];
[item2 setTarget:self];显式设置no target会导致上下文菜单保持禁用状态。
干杯!
亚历克斯
PS:我本想把这篇文章作为评论发布的,但我没有足够的名气来这么做:
https://stackoverflow.com/questions/15185645
复制相似问题