【问题标题】:NSTableView Right Clicked Row IndexNSTableView 右击行索引
【发布时间】:2012-09-19 12:13:52
【问题描述】:

我正在寻找一种从NSTableView 获取右键单击行索引的方法,但我找不到任何委托方法或类属性。任何建议表示赞赏。

【问题讨论】:

    标签: objective-c cocoa nstableview


    【解决方案1】:

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

    对于此解决方案,您不需要为 NSTableView 子类化。 clickedRow 也可以在 NSOutlineView 上找到。

    【讨论】:

    • 我认为这在右键单击一行时不应该起作用,因为 clickedRow 的返回值仅在目标的动作或双动作方法的实现中有意义。
    • 只要在 NSTableView 的目标操作或 doubleAction 方法中调用它,它就可以工作。您是否还有其他需要点击的行的情况?
    • 我认为原始发布者在右键单击一行时要求提供解决方案。据我所知,右键单击不可能触发其中任何一种方法。
    • 根据 10.5 发行说明 (developer.apple.com/library/content/releasenotes/AppKit/…):“要注意的关键是 clickedRow 和 clickedColumn 现在在弹出上下文菜单时都有效。 …当从 NSMenuItem 发送操作时,clickedRow 和 clickedColumn 属性仍然有效。”。我发现这确实有效如果表的menu 插座已设置,如果您覆盖-menuForEvent:,则必须调用super
    • 这个答案工作正常。将 NSTableView 的菜单属性设置为您拥有的 NSMenu 项。设置 NSMenu 的委托。在 menuNeedsUpdate(_: NSMenu) 中,您可以在 NSTableView 上调用 clickedRow()。这确实适用于调用此菜单委托时的右键单击。
    【解决方案2】:

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

    -(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.
    }
    

    【讨论】:

    • 我希望能找到一种不继承 NSTableView 的方法。
    • 格雷厄姆的回答在没有子类化的情况下有效。将 NSTableView 的菜单属性设置为您拥有的 NSMenu 项。设置 NSMenu 的委托。在 menuNeedsUpdate(_: NSMenu) 中,您可以在 NSTableView 上调用 clickedRow()。这确实适用于调用此菜单委托时的右键单击。
    【解决方案3】:

    更新答案

    如果您想在打开菜单时获得点击的行索引,答案是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 工作中获取上下文菜单,但失败了?
    【解决方案4】:

    只需通过在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
    

    【讨论】:

    • 这与 Finder 和 Mail 中的行为不匹配,后者允许您使用上下文菜单对一行进行操作而不影响选择。
    【解决方案5】:

    如果您不需要打开 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)
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      • 2018-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-14
      相关资源
      最近更新 更多