本文介绍了在我的NSOutlineView单元格中,两次调用hitTestForEvent:inRect:ofView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过在接口构建器中设置自定义类,我已经将NSOutlineView的单元格子类化.

I've subclassed the cells of a NSOutlineView, by setting the custom class in interface builder.

我已经实现了此委托方法来配置单元格:

I've implemented this delegate method to configure the cells:

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

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

Also, I've implemented this method in my custom cell class:

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

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

which is invoked twice every time I click on the cell. I'm wondering why not just once. The event type is always MouseDown.

我不知道这是否重要,但是即使单元格没有父母或孩子,它也会被调用两次.因此它不能是单元格层次结构.

I don't know if this matters, but it is invoked twice even if the cell has not parents or children. So it can't be the cells hierarchy.

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

If I can't rely on hitTestForEvent to trigger an action when a specific area of my cell is clicked, which method should I use ?

谢谢

推荐答案

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

重要说明::如果您在 -trackMouse:inRect:ofView:untilMouseUp:中实现自己的鼠标跟踪循环,则您应该将此事实记录在某个地方,因为从总体上讲,它将排除其他三种方法的使用.AppKit框架中的某些 NSCell 子类会执行此操作,并且无法记录它们是否这样做(结果是您要花费数小时来思考为什么 -startTrackingAt:inView:永远不会被调用).

Important Note: If you implement your own mouse tracking loop in -trackMouse:inRect:ofView:untilMouseUp:, you should document this fact somewhere, because generally speaking it will preclude the use of the other three methods. Some of the NSCell subclasses in the AppKit framework do this and fail to document that they have done so (with the result that you’ll ponder for hours why it is that -startTrackingAt:inView: never gets called).

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

How do you implement your own tracking loop? Like this:

- (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];
}

(上面的代码只是在这里输入的,因此通常需要注意;它假设存在一个名为 myClickRect NSRect ,该代码定义了单元格的活动区域.您可能需要从方法顶部的 cellFrame 中进行计算.)

(The above code was just typed in here, so the usual caveats apply; it assumes the existence of an NSRect called myClickRect that defines the active area of your cell. You might need to calculate that from cellFrame at the head of the method.)

很明显,如果它们与您相关,您也可以注意并处理其他事件.

Obviously you can watch for and handle other events too, if they are relevant to you.

也许我还应该补充一点,这三种方法虽然在概念上比较干净,但往往会慢一些,这通常使我更喜欢覆盖 -trackMouse:inRect:ofView:untilMouseUp:如上所示.

Perhaps I should also add that the three method approach, while conceptually cleaner, tends to be quite a bit slower, which generally leads me to prefer overriding -trackMouse:inRect:ofView:untilMouseUp: as shown above.

这篇关于在我的NSOutlineView单元格中,两次调用hitTestForEvent:inRect:ofView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 18:53