NSWindow.contentView.hittest()未到达NSOutlineView的子视图

时间:2017-09-12 14:42:56

标签: macos nsoutlineview hittest

我的应用程序窗口有一个带有三个窗格的splitview;最左边的窗格包含基于视图的大纲视图。

当我单击该大纲视图上的某个位置时,我想确定所单击的层次结构中最底部的子视图。也就是说,单击了哪一行,哪个单元格,以及最终单击了哪个子视图(控件)。

我尝试在托管视图控制器上覆盖mouseDown(with:),但是没有调用它;我怀疑大纲视图以某种方式占用了事件,所以我决定直接在我的NSOutlineView子类本身上覆盖该方法。这有效。但是,从那里开始,我不能在层次结构中继续进行比大纲视图本身更进一步:

类MyOutlineView:NSOutlineView {

override func mouseDown(with event: NSEvent) {
    if let view = self.window?.contentView?.hitTest(event.locationInWindow) {
        Swift.print("\(view.className)")
    }
}

...打印:

  

MyModule的。 MyOutlineView

hittest()的文档内容为:

  

返回视图层次结构中视图的最远后代   (包括其本身)包含指定的点,如果是,则为nil   点完全在视图之外。主要使用此方法   由NSWindow对象确定应该接收哪个视图   鼠标按下事件。您很少需要调用此方法,但是您   可能希望覆盖它以使视图对象隐藏鼠标按下事件   从它的子视图。此方法忽略隐藏的视图。

如何点击测试大纲视图的最顶层子视图?

1 个答案:

答案 0 :(得分:1)

mouseDown(with:)在视图上调用,而不是在控制器上调用。 通常,大纲视图中的控件处理mouseDown。

但是如果你想找到控件,是的,-[NSTableView(NSTableViewRowHeaderSupport) hitTest:]会让事情变得混乱。解决方法:获取行和列,获取单元格视图并在单元格视图上调用hitTest

override func mouseDown(with event: NSEvent) {
    let localPoint = self.convert(event.locationInWindow, from: nil)
    let column = self.column(at: localPoint)
    let row = self.row(at: localPoint)
    if column >= 0 && row >= 0 {
        if let cellView = self.view(atColumn: column, row: row, makeIfNecessary: false) {
            if let cellSuperViewPoint = cellView.superview?.convert(localPoint, from: self) {
                if let view = cellView.hitTest(cellSuperViewPoint) {
                    Swift.print("\(view.className)")
                }
            }
        }
    }
}