NSTableView: detecting a mouse click together with the row and column

心已入冬 提交于 2019-11-28 04:44:26
Peter Lapisu

To catch the user clicking a row (only, when the user clicks a row, not when it is selected programmatically) :

Subclass your NSTableView and declare a protocol

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

Handle the mouse down event (note, the delegate callback is not called when the user clicks outside, maybe you want to handle that too, in that case, just comment out the condition "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];
    }
}

Make your WC, VC conform to ExtendedTableViewDelegate.

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

set the extendedDelegate of the MyTableView to your WC, VC (MyViewController)

somewhere in MyTableView.m

self.myTableView.extendedDelegate = self

Implement the callback in delegate (MyViewController.m)

- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row {
    // have fun
}

There is a simple way.

Tested with Swift 3.0.2 on macOS 10.12.2 and Xcode 8.2.1

Let

tableView.action = #selector(onItemClicked)

Then

@objc private func onItemClicked() {
    print("row \(tableView.clickedRow), col \(tableView.clickedColumn) clicked")
}

I would prefer doing as follows.

Override

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

Provide super implementation;

RequiredRow = row;
RequiredColumn = [tableView clickedColumn];

Hope this helps.

If someone is looking for a Swift 3 version of Peter Lapisu's answer.

Add an extension for the 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, to: 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)
}

Then to use it, make sure you implement the new delegate protocol:

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

The @nonobjc attribute silences the warning about it being close to didClick.

Just in case someone was looking for it in SWIFT and / or for NSOutlineView.

Based on @Peter Lapisu instructions.

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))
        }
    }}

see the tableViewSelectionIsChanging notification, here are the the comments from NSTableView.h

/* Optional - Called when the selection is about to be changed, but note, tableViewSelectionIsChanging: is only called when mouse events are changing the selection and not keyboard events. */

I concede that this might not be the surest way to correlate your mouse clicks, but it is another area to investigate, seeing that you are interested in mouse clicks.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!