NSTableView:检测鼠标点击以及行和列
Posted
技术标签:
【中文标题】NSTableView:检测鼠标点击以及行和列【英文标题】:NSTableView: detecting a mouse click together with the row and column 【发布时间】:2013-09-04 19:30:04 【问题描述】:我试图检测何时在 NSTableView 中发生鼠标点击,以及何时发生,以确定被点击的单元格的行和列。
到目前为止我已经尝试过使用NSTableViewSelectionDidChangeNotification,但是有两个问题:
-
它仅在选择更改时触发,而我希望每次鼠标点击,即使它在当前选定的行上。
调用我的委托时,NSTableView 的 clickedRow 和 clickedColumn 属性均为 -1。
有没有更好(和正确)的方法?
【问题讨论】:
【参考方案1】:有一个简单的方法。
在 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")
【讨论】:
似乎是最好的答案。 一定要设置tableView.target
。
太棒了!这确实是最好的答案
如果你声明像@IBAction private func tableRowWasClicked(_ tableView: NSTableView)
这样的方法,那么在你的XIB或故事板中,你可以将表格视图的action
出口连接到方法而不是设置target
和action
代码。
似乎这不仅是一个很好的答案,而且是它应该工作的方式。因为实现 mouseDown 和类似的方法必须处理当表格放置在 NSScrollView 内时发生移动的大量坐标。【参考方案2】:
捕捉用户点击一行(仅当用户点击一行时,而不是在以编程方式选择它时):
继承您的 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
处理鼠标按下事件(注意,当用户点击外部时不会调用委托回调,也许你也想处理,在这种情况下,只需注释掉条件“@987654322 @")
- (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
【讨论】:
如何处理 mouseEntered & mouseExit 事件?有什么想法吗?【参考方案3】:我更喜欢这样做。
覆盖
-(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;
提供超级实现;
RequiredRow = row;
RequiredColumn = [tableView clickedColumn];
希望这会有所帮助。
【讨论】:
这不仅是由用户操作触发的,如问题“我试图检测何时在 NSTableView 中发生鼠标点击,以及何时发生,以确定行和列”中所述被点击的单元格”,而且每次选择以编程方式更改时 这也会在用户执行点击以外的操作时触发,例如在列表具有焦点时按空格键或键入字母键。【参考方案4】:如果有人正在寻找 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 的警告静音。
【讨论】:
它可以工作,但是当点击项目时,没有选择任何内容【参考方案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))
【讨论】:
mouseDown
不应出现在您的MYOutlineViewDelegate
中【参考方案6】:
查看 tableViewSelectionIsChanging 通知,这里是来自 NSTableView.h 的 cmets
/* 可选 - 在即将更改选择时调用,但请注意,tableViewSelectionIsChanging: 仅在鼠标事件更改选择而不是键盘事件时调用。 */
我承认这可能不是关联鼠标点击的最可靠方法,但这是另一个需要调查的领域,因为您对鼠标点击感兴趣。
【讨论】:
我不认为这涵盖了以下问题的要求:“我希望每次鼠标点击,即使它在当前选定的行上。”以上是关于NSTableView:检测鼠标点击以及行和列的主要内容,如果未能解决你的问题,请参考以下文章
delphi中获取memo鼠标所在位置的行和列(通过EM_GETRECT消息取得Rect后,自己算一下)