我的程序中具有以下 View 层次结构设置。

Window
+ContentView (Subview of Window)
++MyCustomView (Subview of ContentView)
++MyCustomOpaqueView (Subview of ContentView)
+++TextField (Subview of MyCustomOpaqueView)

当用户单击TextField时,其内部的光标开始闪烁。
每次闪烁时,都会在MyCustomView上调用drawRect。没什么大不了的,但是我想知道为什么吗?

在MyCustomOpaqueView中,我像这样实现isOpaque,
- (BOOL)isOpaque {return YES;}

我认为,如果传递给drawRect的NSRect完全被不透明的 View 所遮盖,则这将阻止消息传递给MyCustomView中的drawRect,但是当光标闪烁时,MyCustomView仍会发送带有NSRect的drawRect消息,该消息完全位于不透明的 View 后面。

我是否错过了一个关键概念,或者这是闪烁的光标的怪癖?

最佳答案

根据乔什·卡斯韦尔(Josh Caswell)的建议,自行解决此问题。

我在CocoaHeads session 上问了这个问题。我建议看一下NSView的hitTest。因此,在我的两个自定义 View 上,我都覆盖了NSView的hittest函数,如下所示:

- (NSView*) hitTest:(NSPoint)aPoint {
    static int depth = 1;
    NSLog([NSString stringWithFormat:@"%%%dd ENTER %%@ - hitTest", depth],
          depth, [[self class] description]);
    depth++;
    NSView *hitView = [super hitTest:aPoint];
    depth--;
    NSLog([NSString stringWithFormat:@"%%%dd EXIT %%@ - hitTest: %%@", depth],
          depth, [[self class] description], [[hitView class] description]);
    return hitView;
}

以下是输出:

MyCustomView是contentView的 subview 。
MyOpaqueCustomView(OCV)是contentView的 subview 。
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
MyCustomView - Dirty Rect: {{49, 189}, {127, 28} //!!Focus Ring Around Text Field
OCV - Dirty Rect: : {{49, 189}, {127, 28}}
testTextField isOpaque? Yes
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 ENTER MyCustomView - hitTest
1 EXIT MyCustomView - hitTest: MyCustomView
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}} //!!EVERY BLINK
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}
MyCustomView - Dirty Rect: {{64, 194}, {1, 17}}

MyCustomView是contentView的 subview 。
MyOpaqueCustomView(OCV)是MyCustomView的 subview 。
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 EXIT MyCustomView - hitTest: NSTextField
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 EXIT MyCustomView - hitTest: NSTextField
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 EXIT MyCustomView - hitTest: NSTextView
OCV - Dirty Rect: : {{49, 189}, {127, 28}} //!!FOCUS RING
testTextField isOpaque? Yes
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 EXIT MyCustomView - hitTest: NSTextView
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextView
1 EXIT MyCustomView - hitTest: NSTextView
1 ENTER MyCustomView - hitTest
1 ENTER OCV - hitTest
1 EXIT OCV - hitTest: NSTextField
1 EXIT MyCustomView - hitTest: NSTextField
//!!BLINKING HERE - But no dirtyRects.

因此,对hitTest的响应似乎定义了将重绘哪些 View 。

10-08 05:56