NSView setNeedDisplay:rect 会导致重绘比所需更大的区域



我需要重绘一些NSView的一部分。

- (IBAction)onUpdateView:(id)sender
{
    NSRect updatedRect = ... // Redraw updated area only.
    [self.view setNeedsDisplayInRect:updatedRect];
}

当我使用这个简单明了的解决方案时,Quartz Debug 会突出显示更大区域的重绘 - 直到视图的整个区域。

我注意到,如果 [NSView setNeedsDisplayInRect] 的调用被推迟到下一个运行循环周期,或者我只是执行 [runloop runUntilDate:+0],问题就会消失:

- (IBAction)onUpdate:(id)sender
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self setNeedsDisplayInRect:updatedRect];
    });
}

- (IBAction)onUpdateAndRunLoop:(id)sender
{
    [self.view setNeedsDisplayInRect:updatedRect];
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:0.0]]; // EEW
}

但是如果在mouseDown处理程序中调用setNeedsDisplayInRect,它可以在没有所有这些黑客的情况下工作:

-(void)mouseUp:(NSEvent*)event
{
    NSPoint p = [self convertPoint:[event locationInWindow] fromView:nil];
    int size = 100;
    [self setNeedsDisplayInRect:NSMakeRect(p.x-size/2, p.y-size/2, size, size)];
}

这是怎么回事,该怎么办?

此问题的隔离 Xcode 项目在这里:http://beta.kalinsky.ru/wtf/testRedraw.tar.gz

是什么让你如此确定这是不良行为?我在 Quartz 调试器下看到的行为表明,当我点击"更新"按钮时,单击按钮的矩形与传递的 dirtyRect 的矩形的交点会闪烁。这是意料之中的,因为系统将所有需要的绘图合并到运行循环的同一通道(鼠标向上)以提高效率。

您的其他黑客方法会绕过此行为,因为按钮的状态在一次(实际上是两次:鼠标按下和鼠标向上)中处理,而视图的更新在后续传递中处理。如果您密切关注延迟绘图单击中的更新闪烁(按钮向下闪烁,再次向上闪烁,然后视图的脏区闪烁),则会验证这一点。对视图本身的点击不涉及其他内容(好吧,从技术上讲,它是不透明的祖先),因此所有视图的脏矩形的联合仅限于您请求的矩形。

我希望这有所帮助。

最新更新