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

后端 未结 6 536
Happy的楠姐
Happy的楠姐 2020-12-08 01:10

I\'m trying to detect when a mouse click occurs in an NSTableView, and when it does, to determine the row and column of the cell that was clicked.

So far I\'ve tried

相关标签:
6条回答
  • 2020-12-08 01:24

    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")
    }
    
    0 讨论(0)
  • 2020-12-08 01:34

    If someone is looking for a Swift 3/4/5 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, 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)
    }
    

    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.

    0 讨论(0)
  • 2020-12-08 01:36

    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))
            }
        }}
    
    0 讨论(0)
  • 2020-12-08 01:41

    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.

    0 讨论(0)
  • 2020-12-08 01:43

    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
    }
    
    0 讨论(0)
  • 2020-12-08 01:44

    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.

    0 讨论(0)
提交回复
热议问题