我有一个带有源列表(NSOutlineView)的窗口。我的源列表只有两个级别。第一级是标题,第二级是数据。我想在一些数据单元格上有一个上下文菜单。不是全部。
首先,我尝试在表格单元格视图上附加一个表示数据单元格的菜单 - >没有任何反应。
其次,我在IB中的大纲视图上附加了一个菜单 - >每个单元格(标题和数据)上打开上下文菜单。我搜索停止打开菜单,但我找不到任何东西。
你有什么想法吗?
谢谢
OS X 10.8.2 Lion,Xcode 4.5.2,SDK 10.8
答案 0 :(得分:7)
如果您是NSOutlineView的子类,只有当用户点击了正确的行时,您才可以覆盖menuForEvent:
以返回菜单。这是一个例子:
- (NSMenu *)menuForEvent:(NSEvent *)event;
{
//The event has the mouse location in window space; convert it to our (the outline view's) space so we can find which row the user clicked on.
NSPoint point = [self convertPoint:[event locationInWindow] fromView:nil];
NSInteger row = [self rowAtPoint:point];
//If the user did not click on a row, or is not exactly one level down from the top level of hierarchy, return nil—that is, no menu.
if ( row == -1 || [self levelForRow:row] != 1 )
return nil;
//Create and populate a menu.
NSMenu *menu = [[NSMenu alloc] init];
NSMenuItem *delete = [menu addItemWithTitle:NSLocalizedString( @"Delete", @"" ) action:@selector(delete:) keyEquivalent:@""];
[self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
//Set the Delete menu item's represented object to the clicked-on item. If the user chooses this item, we'll retrieve its represented object so we know what to delete.
[delete setRepresentedObject:[self itemAtRow:row]];
return menu;
}
这假设我们正在使用ARC进行编译,因此您无需自动释放正在创建的菜单对象。
答案 1 :(得分:0)
从您的问题中不清楚您的大纲是基于视图还是基于单元格。这很重要。
如果您是基于视图的,那么您的视图实例可以实现
- (NSMenu *)menuForEvent:(NSEvent *)theEvent
并返回适合该项目的菜单 - 或者根本不需要菜单。
如果您是基于单元格的,或者由于某种原因您不想在视图类中处理此问题,则需要将NSOutlineView子类化并在那里实现- (NSMenu *)menuForEvent:(NSEvent *)theEvent
。再次,您将找出哪个单元格被击中或活动,并从中确定您想要的菜单。
答案 2 :(得分:0)
- (void)rightMouseDown:(NSEvent *)event
NSView不会将此传递给下一个视图,此方法查看当前类是否具有menuForEvent:,如果确实如此,则调用它。如果没有那么它就完成了,没有别的事情会发生。这就是为什么你不会看到NSTableCellView响应menuForEvent的原因:因为表视图吞下了rightMouseDown:。
您可以继承tableview并处理rightMouseDown:事件并调用NSTableCellView的rightMouseDown:并处理显示您在故事板中构建的菜单并连接到您的NSTableViewCell。
这是我在子类NSTableView中的解决方案:
- (void)rightMouseDown:(NSEvent *)event
{
for (NSTableRowView *rowView in self.subviews) {
for (NSView *tableCellView in [rowView subviews]) {
if (tableCellView) {
NSPoint eventPoint = [event locationInWindow];
// NSLog(@"Window Point: %@", NSStringFromPoint(eventPoint));
eventPoint = [self convertPoint:eventPoint toView:nil];
eventPoint = [self convertPoint:eventPoint toView:self];
// NSLog(@"Table View Point: %@", NSStringFromPoint(eventPoint));
NSRect newRect = [tableCellView convertRect:[tableCellView bounds] toView:self];
// NSLog(@"Rect: %@", NSStringFromRect(newRect));
BOOL rightMouseDownInTableCellView = [tableCellView mouse:eventPoint inRect:newRect];
// NSLog(@"Mouse in view: %hhd", mouseInView);
if (rightMouseDownInTableCellView) {
if (tableCellView) {
// Lets be safe and make sure that the object is going to respond.
if ([tableCellView respondsToSelector:@selector(rightMouseDown:)]) {
[tableCellView rightMouseDown:event];
}
}
}
}
}
}
}
这将找到鼠标右键事件发生的位置,检查我们是否有正确的视图并将rightMouseDown:传递给该视图。
如果此解决方案适合您,请告诉我。