你如何添加上下文灵敏菜单NSOutlineView(即右键菜单)(How do you add co

2019-07-02 17:39发布

你如何添加到右键单击一个行中的NSOutlineView所以可以说删除对象或其他活动的能力。 (即就像当你右键点击在苹果Mail应用程序的文件夹上)

我想我走了一半,我有NSOutlineView的一个子类,让我赶上点击右键并显示基于所选行,而不是鼠标点击行上的上下文菜单。

@implementation NSContextOutlineView

    - (NSMenu *)defaultMenu {
        if([self selectedRow] < 0) return nil;
        NSMenu *theMenu = [[[NSMenu alloc] initWithTitle:@"Model browser context menu"] autorelease];
        [theMenu insertItemWithTitle:@"Add package" action:@selector(addSite:) keyEquivalent:@"" atIndex:0];
        NSString* deleteItem = [NSString stringWithFormat: @"Remove '%i'", [self selectedRow]];
        [theMenu insertItemWithTitle: deleteItem action:@selector(removeSite:) keyEquivalent:@"" atIndex:1];
        return theMenu;
    }

    - (NSMenu *)menuForEvent:(NSEvent *)theEvent {
        return [self defaultMenu];  
    }
@end

很抱歉,如果答案是显而易见的我都无法找到这个网上或文档中的任何帮助。

由于void对于答案,这导致我使用这个:

- (NSMenu *)menuForEvent:(NSEvent *)theEvent {
    NSPoint pt = [self convertPoint:[theEvent locationInWindow] fromView:nil];
    id item = [self itemAtRow: [self rowAtPoint:pt]];
    return [self defaultMenuFor: item];
}

Answer 1:

在你menuForEvent方法,你可以找出发生在哪一行的点击。 您可以传递一个作为参数传递给你的defaultMenu方法-也许称之为defaultMenuForRow:

-(NSMenu*)menuForEvent:(NSEvent*)evt 
{
    NSPoint pt = [self convertPoint:[evt locationInWindow] fromView:nil];
    int row=[self rowAtPoint:pt];
    return [self defaultMenuForRow:row];
}

现在,您可以为您构建在事件中发现该行的菜单...

-(NSMenu*)defaultMenuForRow:(int)row
{
    if (row < 0) return nil;

    NSMenu *theMenu = [[[NSMenu alloc] 
                                initWithTitle:@"Model browser context menu"] 
                                autorelease];
    [theMenu insertItemWithTitle:@"Add package" 
                          action:@selector(addSite:) 
                   keyEquivalent:@"" 
                         atIndex:0];
    [theMenu insertItemWithTitle:[NSString stringWithFormat:@"Remove '%i'", row] 
                          action:@selector(removeSite:) 
                   keyEquivalent:@"" 
                         atIndex:0];
    // you'll need to find a way of getting the information about the 
    // row that is to be removed to the removeSite method
    // assuming that an ivar 'contextRow' is used for this
    contextRow = row;

    return theMenu;        
}

此外,如在评论中已经提到的,你真的不应该用你自己的类NS-前缀。 有在未来再加上它会混淆大家的冲突潜在的是看你的代码 - 包括你自己:)

希望这可以帮助...



Answer 2:

下面是使用一个子类,并扩展了默认的一个雨燕2.0例如NSOutlineDelegate这样你就可以在委托定义菜单。

protocol MenuOutlineViewDelegate : NSOutlineViewDelegate {
    func outlineView(outlineView: NSOutlineView, menuForItem item: AnyObject) -> NSMenu?
}

class MenuOutlineView: NSOutlineView {

    override func menuForEvent(event: NSEvent) -> NSMenu? {
        let point = self.convertPoint(event.locationInWindow, fromView: nil)
        let row = self.rowAtPoint(point)
        let item = self.itemAtRow(row)

        if (item == nil) {
            return nil
        }

        return (self.delegate() as! MenuOutlineViewDelegate).outlineView(self, menuForItem: item!)
    }

}


Answer 3:

很久以后比OP的问题,但对于其他人一样我想知道,这里是我的解决方案。 它还需要继承NSOutlineView,这不是苹果的文档鼓励,反正...

而不是覆盖menuForEvent:我重写rightMouseDown:

- (void)rightMouseDown:(NSEvent *)event {
    NSPoint pt = [self convertPoint:[event locationInWindow] fromView:nil];
    NSInteger row = [self rowAtPoint:pt];
    id item = [self itemAtRow:row];
    NSMenu *menu;
    //set the menu to one you have defined either in code or IB through outlets
    self.menu = menu;
    [super rightMouseDown:event];
}

这有保持委托的优势,此后调用更新菜单,也保留行概述了点击右键。



Answer 4:

如果你愿意,你可以将菜单中的单个细胞视图或行观点,并与界面生成器生成它:

@implementation BSMotleyOutlineView

-(NSMenu *)menuForEvent:(NSEvent *)event
{
    NSPoint pt = [self convertPoint:[event locationInWindow] fromView:nil];
    NSInteger row = [self rowAtPoint:pt];
    if (row >= 0) {
        NSTableRowView* rowView = [self rowViewAtRow:row makeIfNecessary:NO];
        if (rowView) {
            NSInteger col = [self columnAtPoint:pt];
            if (col >= 0) {
                NSTableCellView* cellView = [rowView viewAtColumn:col];
                NSMenu* cellMenu = cellView.menu;
                if(cellMenu) {
                    return cellMenu;
                }
            }
            NSMenu* rowMenu = rowView.menu;
            if (rowMenu) {
                return rowMenu;
            }
        }
    }
    return [super menuForEvent:event];
}
@end


文章来源: How do you add context senstive menu to NSOutlineView (ie right click menu)