cocoa - NSTableView: detectando un clic del mouse junto con la fila y la columna
swift cell (6)
En caso de que alguien lo esté buscando en SWIFT y / o para NSOutlineView .
Basado en las instrucciones de @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))
}
}}
Estoy tratando de detectar cuándo se produce un clic del mouse en un NSTableView y, cuando lo hace, para determinar la fila y la columna de la celda en la que se hizo clic.
Hasta ahora he intentado usar NSTableViewSelectionDidChangeNotification, pero hay dos problemas:
- Solo se dispara cuando la selección cambia, mientras que quiero hacer clic con el mouse, incluso si está en la fila seleccionada actualmente.
- Las propiedades clickedRow y clickedColumn de NSTableView son ambas -1 cuando se llama a mi delegado.
¿Hay una manera mejor (y correcta) de hacer esto?
Hay una forma sencilla.
Probado con Swift 3.0.2 en macOS 10.12.2 y Xcode 8.2.1
Dejar
tableView.action = #selector(onItemClicked)
Entonces
@objc private func onItemClicked() {
print("row /(tableView.clickedRow), col /(tableView.clickedColumn) clicked")
}
Para atrapar al usuario haciendo clic en una fila (solo cuando el usuario hace clic en una fila, no cuando se selecciona mediante programación):
Subclase su NSTableView y declare un protocolo
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
Maneje el evento con el mouse hacia abajo (tenga en cuenta que la devolución de llamada de delegado no se llama cuando el usuario hace clic en el exterior, tal vez usted también quiera manejar eso, en ese caso, simplemente comente la condición " 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];
}
}
Haga que su WC, VC se ajuste a ExtendedTableViewDelegate .
@interface MyViewController : DocumentBaseViewController<ExtendedTableViewDelegate, NSTableViewDelegate, NSTableViewDataSource>
establezca la ExtendedDelegate de MyTableView en su WC, VC (MyViewController)
en algún lugar de MyTableView.m
self.myTableView.extendedDelegate = self
Implementar la devolución de llamada en delegado (MyViewController.m)
- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row {
// have fun
}
Preferiría hacer lo siguiente.
Anular
-(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;
Proporcionar super implementación;
RequiredRow = row;
RequiredColumn = [tableView clickedColumn];
Espero que esto ayude.
Si alguien está buscando una versión Swift 3 de la respuesta de Peter Lapisu.
Agregue una extensión para el 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)
}
Luego, para usarlo, asegúrate de implementar el nuevo protocolo de delegado:
extension MyViewController: NSTableViewClickableDelegate {
@nonobjc func tableView(_ tableView: NSTableView, didClickRow row: Int) {
Swift.print("Clicked row /(row)")
}
}
El atributo @nonobjc
silencia la advertencia de que está cerca de didClick.
vea la notificación de tableViewSelectionIsChanging , aquí están los comentarios de NSTableView.h
/ * Opcional: se llama cuando la selección está a punto de cambiarse, pero note, tableViewSelectionIsChanging: solo se llama cuando los eventos del mouse cambian la selección y no los eventos del teclado. * /
Admito que esta podría no ser la forma más segura de correlacionar los clics del mouse, pero es otra área para investigar, ya que está interesado en los clics del mouse.