NSTableView 右键点击的行索引

17
我正在寻找一种方法来获取从 NSTableView 中右键单击的行索引,但我无法找到任何委托方法或类属性。欢迎提供任何建议。
6个回答

23

使用 NSTableView 方法 - (NSInteger)clickedRow 获取最后一次点击的行索引。返回的 NSInteger 将是右键单击行的索引。

您不需要为此解决方案子类化 NSTableViewclickedRowNSOutlineView 上也可用。


2
我认为右键单击行时这不应该起作用,因为clickedRow的返回值仅在目标实现操作或双击操作方法时才有意义。 - Ira Cooke
1
只要从NSTableView的目标操作或doubleAction方法中调用,这就有效。您是否有另一种情况需要获取所点击的行? - Graham Miln
4
我认为原帖的作者询问了一个右键单击行时的解决方案。据我了解,使用右键单击无法触发上述任何一种方法。 - Ira Cooke
5
根据10.5版本的发行说明(https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKitOlderNotes/index.html#X10_5Notes):“需要注意的关键是,当弹出上下文菜单时,clickedRow和clickedColumn现在都有效。... 在从NSMenuItem发送操作时,clickedRow和clickedColumn属性仍将有效。” 我发现,只有当表格的“menu”输出口设置,并且您覆盖“-menuForEvent:”时,您必须调用“super”,才能使此项有效。 - Michael Tsai
2
这个答案是正确的。将NSTableView的菜单属性设置为您拥有的NSMenu项。设置该NSMenu的代理。在menuNeedsUpdate(_: NSMenu)中,您可以在NSTableView上调用clickedRow()。在调用此菜单委托时,对于右键单击,它确实有效。 - Giles
显示剩余2条评论

11

虽然我没有做过这个,但我很确定你可以通过覆盖NSView- (NSMenu*)menuForEvent:(NSEvent*)theEvent来实现。这个链接中的示例进行了点转换以确定索引。

-(NSMenu*)menuForEvent:(NSEvent*)theEvent
{
    NSPoint mousePoint = [self convertPoint:[theEvent locationInWindow] fromView:nil];
   int row = [self rowAtPoint:mousePoint];
   // Produce the menu here or perform an action like selection of the row.
}

3
我希望找到一种不用子类化NSTableView的方法。 - Abcd Efg
1
Graham的下面的答案可以在不使用子类化的情况下工作。将NSTableView的菜单属性设置为您拥有的NSMenu项。设置该NSMenu的代理。在menuNeedsUpdate(_: NSMenu)中,您可以在NSTableView上调用clickedRow()。这确实适用于在调用此菜单委托时右键单击的情况。 - Giles

7

更新的回答

如果您想在菜单打开时获取点击行的索引,则答案是NSTableView.clickedRow。无论如何,此属性仅在特定时刻可用,通常为-1

这个索引何时可用?即在NSMenuDelegate.menuWillOpen方法中。因此,您需要符合代理并在您的类上实现该方法,并访问clickedRow属性。完成了。

final class FileNavigatorViewController: NSViewController, NSMenuDelegate {
    let ov = NSOutlineView() // Assumed you setup this properly.
    let ctxm = NSMenu()
    override func viewDidLoad() {
        super.viewDidLoad()
        ov.menu = ctxm
        ctxm.delegate = self
    }
    func menuWillOpen(_ menu: NSMenu) {
        print(outlineView.clickedRow)
    }
}

在您单击菜单项之前,所单击的行索引是可用的。 因此,这也适用于此情况。

final class FileNavigatorViewController: NSViewController {
    let ov = NSOutlineView() // Assumed you setup this properly.
    let ctxm = NSMenu()
    let item1 = NSMenuItem()
    override func viewDidLoad() {
        super.viewDidLoad()
        ov.menu = ctxm
        ov.addItem(item1)
        ov.target = self
        ov.action = #selector(onClickItem1(_:))
    }
    @objc
    func onClickItem1(_: NSObject?) {
        print(outlineView.clickedRow)
    }
}

我在 macOS Sierra (10.12.5) 上进行了测试。


旧回答

从 OS X 10.11 开始,Apple 终于添加了一种简单访问 clickedRow 的方法。只需子类化 NSTableView 并覆盖此方法,您将得到 clickedRow(就我所知)。

func willOpenMenu(menu: NSMenu, withEvent event: NSEvent)

这需要子类化处理,但无论如何,访问clickedRow的最干净和最简单的方法是。

此外,还有一种配对方法。

func didCloseMenu(menu: NSMenu, withEvent event: NSEvent?)

如果您能提供一个可工作的示例,那将非常棒。我已经花了最近两天的时间来让NSTableCellView中的上下文菜单正常工作,但是失败了。 - ixany

3

通过在NSTableView子类中实现menuForEvent:,可以在右键单击时选择行:

@implementation MyTableView

- (NSMenu *)menuForEvent:(NSEvent *)theEvent
{
    int row = [self rowAtPoint:[self convertPoint:theEvent.locationInWindow fromView:nil]];
    if (row == -1) 
        return nil;
    if (row != self.selectedRow)
        [self selectRowIndexes:[NSIndexSet indexSetWithIndex:row] byExtendingSelection:NO];
    return self.menu;
}

@end

2
这与Finder和Mail中的行为不匹配,它们允许您使用上下文菜单在不影响选择的情况下对行进行操作。 - Michael Tsai

0

如果您不需要打开NSMenu,但需要知道“右键单击行号”的操作,我认为最简单的方法如下。(Swift4代码)不需要任何其他连接的外部NSMenu类。

class SomeViewController: NSViewController, NSTableViewDataSource, NSTableViewDelegate {
  @IBOutlet weak var tableView: NSTableView!
  ...

  override func viewDidLoad() {
    ...
    tableView.action = #selector(some method()) // left single click action
    tableView.doubleAction = #selector(someMethod()) // left double click action
  }

  // right click action
  override func rightMouseDown(with theEvent: NSEvent) {
    let point = tableView.convert(theEvent.locationInWindow, from: nil)
    let row = tableView.row(at: point)
    print("right click")
    print(row)
  }

0

我有同样的问题,但我还需要一个可以与多个选择行一起使用的解决方案(因为当选择多行并右键单击其中一行时,NSTableView会突出显示所有选中的行)。这是我在NSTableView子类中添加的属性:

var rightClickRowIndexes: IndexSet {
    if clickedRow >= 0 {
        return selectedRowIndexes.contains(clickedRow) ? selectedRowIndexes : IndexSet(integer: clickedRow)
    } else {
        return IndexSet()
    }
}

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接