objective-c - hitTestForEvent :inRect:ofView is invoked twice in my NSOutlineView cells

标签 objective-c cocoa

通过在界面生成器中设置自定义类,我对 NSOutlineView 的单元格进行了子类化。

我已经实现了这个委托(delegate)方法来配置单元格:

- (void)outlineView:(NSOutlineView *)outlineView willDisplayCell:(id)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item

此外,我已在自定义单元类中实现了此方法:

- (NSUInteger)hitTestForEvent:(NSEvent *)event inRect:(NSRect)cellFrame ofView:(NSView *)controlView 

每次我单击单元格时都会调用两次。我想知道为什么不只一次。事件类型始终为 MouseDown。

我不知道这是否重要,但即使单元格没有 parent 或 child ,它也会被调用两次。所以它不可能是单元格层次结构。

如果我不能依靠 hitTestForEvent 在单击单元格的特定区域时触发操作,我应该使用哪种方法?

谢谢

最佳答案

-hitTestForEvent:inRect:ofView完全是用来触发操作的错误方法。您应该使用 -trackMouse:inRect:ofView:untilMouseUp: -startTrackingAt:inView:-continueTracking:at: inView:-stopTracking:at:inView:mouseIsUp:

重要提示:如果您在 -trackMouse:inRect:ofView:untilMouseUp: 中实现自己的鼠标跟踪循环,您应该在某处记录这一事实,因为一般来说它会排除其他三种方法的使用。 AppKit 框架中的一些 NSCell 子类会执行此操作,但无法记录它们已这样做(结果您将思考几个小时为什么会出现 -startTrackingAt:inView: 永远不会被调用)。

您如何实现自己的跟踪循环?像这样:

- (BOOL)trackMouse:(NSEvent *)theEvent inRect:(NSRect)cellFrame
            ofView:(NSView *)controlView untilMouseUp:(BOOL)untilMouseUp
{
  NSPoint pos = [controlView convertPoint:[theEvent locationInWindow]
                                 fromView:nil];

  if ([theEvent type] == NSLeftMouseDown && NSPointInRect (pos, myClickRect)) {
    NSWindow *window = [controlView window];
    NSEvent *myEvent;
    NSDate *endDate = [NSDate distantFuture];

    while ((myEvent = [window nextEventMatchingMask:(NSLeftMouseDragged
                                                     |NSLeftMouseUp)
                                          untilDate:endDate
                                             inMode:NSEventTrackingRunLoopMode
                                            dequeue:YES])) {
      if ([myEvent type] != NSLeftMouseUp)
        continue;

      pos = [controlView convertPoint:[theEvent locationInWindow]
                             fromView:nil];

      if (NSPointInRect (pos, myClickRect)) {
        // React somehow
      }

      return YES;
    }
  }

  return [super trackMouse:theEvent inRect:cellFrame ofView:controlView
              untilMouseUp:untilMouseUp];
}

(上面的代码只是在这里输入的,所以通常的注意事项适用;它假设存在一个名为 myClickRectNSRect ,它定义了单元格的事件区域.您可能需要从方法开头的 cellFrame 计算该值。)

显然,如果其他事件与您相关,您也可以监视和处理它们。

也许我还应该补充一点,三方法方法虽然在概念上更清晰,但往往速度要慢一些,这通常导致我更喜欢覆盖 -trackMouse:inRect:ofView:untilMouseUp: 作为如上所示。

关于objective-c - hitTestForEvent :inRect:ofView is invoked twice in my NSOutlineView cells,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10649379/

相关文章:

macos - 在 macOS 窗口上插入 X - 和 + 按钮

objective-c - 遍历对象的 NSMutableArray

cocoa - pyobjc 中的 NSThread 或 python 线程模块?

macos - 尽管 header 注释,在 Swift 中采用 NSTextFinderBarContainer 协议(protocol)会强制变量初始化

objective-c - 在 Core Graphics 中绘制三角形

ios - Objective-C中另一个线程中的计时器

ios - 如何让我的导航栏在 iOS 7 上完全透明?

ios - 如何保留对符合 Swift 协议(protocol)的类对象的引用

objective-c - 何时使用 .xcconfig 文件

objective-c - 实现/使用outlineView :isGroupItem