NSTableView: обнаружение щелчка мыши вместе со строкой и столбцом
Я пытаюсь обнаружить, когда щелчок мыши происходит в NSTableView, и когда он это делает, чтобы определить строку и столбец ячейки, на которую было нажато.
До сих пор я пытался использовать NSTableViewSelectionDidChangeNotification, но есть две проблемы:
- Он запускается только при изменении выбора, тогда как я хочу, чтобы каждый щелчок мыши, даже если он находится в текущей выбранной строке.
- Свойства clickedRow и clickedColumn для NSTableView равны -1, когда вызывается мой делегат.
Есть ли лучший (и правильный) способ сделать это?
Ответы
Ответ 1
Чтобы поймать пользователя, щелкающего по строке (только, когда пользователь щелкает по строке, а не когда она выбирается программно):
Подкласс вашего 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>
установите extendedDelegate MyTableView для вашего WC, VC (MyViewController)
где-то в MyTableView.m
self.myTableView.extendedDelegate = self
Реализуйте обратный вызов в делегате (MyViewController.m)
- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row {
// have fun
}
Ответ 2
Существует простой способ.
Протестировано с Swift 3.0.2 на macOS 10.12.2 и Xcode 8.2.1
Пусть
tableView.action = #selector(onItemClicked)
Тогда
@objc private func onItemClicked() {
print("row \(tableView.clickedRow), col \(tableView.clickedColumn) clicked")
}
Ответ 3
Я бы предпочел сделать следующее.
Переопределить
-(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;
Обеспечить супер-реализацию;
RequiredRow = row;
RequiredColumn = [tableView clickedColumn];
Надеюсь, что это поможет.
Ответ 4
Если кто-то ищет версию ответа Swift 3 Питера Лапису.
Добавьте расширение для 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)
}
Затем, чтобы использовать его, убедитесь, что вы реализуете новый протокол делегатов:
extension MyViewController: NSTableViewClickableDelegate {
@nonobjc func tableView(_ tableView: NSTableView, didClickRow row: Int) {
Swift.print("Clicked row \(row)")
}
}
Атрибут @nonobjc
отключает предупреждение о том, что он близок к didClick.
Ответ 5
На всякий случай кто-то искал его в 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))
}
}}
Ответ 6
см. уведомление tableViewSelectionIsChanging, вот комментарии от NSTableView.h
/*
Необязательно - вызывается, когда выбор будет изменен, но обратите внимание, tableViewSelectionIsChanging: вызывается только тогда, когда события мыши меняют выбор, а не события клавиатуры.
*/
Я признаю, что это не самый надежный способ сопоставить щелчки мыши, но это еще одна область для исследования, потому что вас интересуют щелчки мышью.