28

我试图检测何时在 NSTableView 中发生鼠标单击,以及何时发生,以确定单击的单元格的行和列。

到目前为止,我已经尝试使用 NSTableViewSelectionDidChangeNotification,但是有两个问题:

  1. 它仅在选择更改时触发,而我希望每次鼠标单击,即使它位于当前选定的行上。
  2. 当我的委托被调用时, NSTableView 的 clickedRow 和 clickedColumn 属性都是-1。

有没有更好(和正确)的方法来做到这一点?

4

6 回答 6

69

有一个简单的方法。

在 macOS 10.12.2 和 Xcode 8.2.1 上使用 Swift 3.0.2 测试

tableView.action = #selector(onItemClicked)

然后

@objc private func onItemClicked() {
    print("row \(tableView.clickedRow), col \(tableView.clickedColumn) clicked")
}
于 2016-12-30T17:18:08.230 回答
27

要捕获用户单击一行(仅当用户单击一行时,而不是在以编程方式选择它时):

子类化你的 NSTableView 并声明一个协议

MyTableView.h

@protocol ExtendedTableViewDelegate <NSObject>

- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row;

@end

@interface MyTableView : NSTableView

@property (nonatomic, weak) id<ExtendedTableViewDelegate> extendedDelegate;

@end

MyTableView.m

处理鼠标按下事件(注意,当用户点击外部时不会调用委托回调,也许您也想处理它,在这种情况下,只需注释掉条件“ if (clickedRow != -1)”)

- (void)mouseDown:(NSEvent *)theEvent {

    NSPoint globalLocation = [theEvent locationInWindow];
    NSPoint localLocation = [self convertPoint:globalLocation fromView:nil];
    NSInteger clickedRow = [self rowAtPoint:localLocation];

    [super mouseDown:theEvent];

    if (clickedRow != -1) {
        [self.extendedDelegate tableView:self didClickedRow:clickedRow];
    }
}

使您的 WC、VC 符合 ExtendedTableViewDelegate

@interface MyViewController : DocumentBaseViewController<ExtendedTableViewDelegate, NSTableViewDelegate,  NSTableViewDataSource>

将 MyTableView 的 extendedDelegate 设置为您的 WC、VC (MyViewController)

MyTableView.m中的某处

self.myTableView.extendedDelegate = self

在委托中实现回调(MyViewController.m)

- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row {
    // have fun
}
于 2013-10-29T14:38:33.033 回答
9

我宁愿做如下。

覆盖

-(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;

提供超级实现;

RequiredRow = row;
RequiredColumn = [tableView clickedColumn];

希望这可以帮助。

于 2013-09-05T06:43:24.557 回答
7

如果有人正在寻找Peter Lapisu 答案的Swift 3/4/5版本:

为 NSTableView 添加一个扩展(NSTableView+Clickable.swift):

import Foundation
import Cocoa

extension NSTableView {
    open override func mouseDown(with event: NSEvent) {
        let globalLocation = event.locationInWindow
        let localLocation = self.convert(globalLocation, from: nil)
        let clickedRow = self.row(at: localLocation)

        super.mouseDown(with: event)

        if (clickedRow != -1) {
            (self.delegate as? NSTableViewClickableDelegate)?.tableView(self, didClickRow: clickedRow)
        }
    }
}

protocol NSTableViewClickableDelegate: NSTableViewDelegate {
    func tableView(_ tableView: NSTableView, didClickRow row: Int)
}

然后使用它,确保你实现了新的委托协议:

extension MyViewController: NSTableViewClickableDelegate {
    @nonobjc func tableView(_ tableView: NSTableView, didClickRow row: Int) {
        Swift.print("Clicked row \(row)")
    }
}

@nonobjc属性使有关它接近 didClick 的警告静音。

于 2017-02-13T22:38:33.617 回答
4

以防万一有人在SWIFT和/或NSOutlineView中寻找它。

基于@Peter Lapisu 说明。

class MYOutlineViewDelegate: NSOutlineView, NSOutlineViewDelegate,NSOutlineViewDataSource{
//....
}    
extension MYOutlineViewDelegate{
    func outlineView(outlineView: NSOutlineView, didClickTableRow item: AnyObject?) {
        //Click stuff
    }

    override func mouseDown(theEvent: NSEvent) {
        let globalLocation:NSPoint  = theEvent.locationInWindow
        let localLocation:NSPoint  = self.convertPoint(globalLocation, fromView: nil)
        let clickedRow:Int = self.rowAtPoint(localLocation)

        super.mouseDown(theEvent)

        if (clickedRow != -1) {
            self.outlineView(self, didClickTableRow: self.itemAtRow(clickedRow))
        }
    }}
于 2015-05-07T16:26:07.290 回答
-2

查看tableViewSelectionIsChanging通知,这里是来自 NSTableView.h 的评论

/* 可选 - 在即将更改选择时调用,但请注意,tableViewSelectionIsChanging: 仅在鼠标事件更改选择而不是键盘事件时调用。*/

我承认这可能不是关联鼠标点击的最可靠方法,但这是另一个需要调查的领域,因为您对鼠标点击感兴趣。

于 2014-11-29T17:09:50.097 回答