如何在不重绘整个视图的情况下更新NSView的一部分

时间:2009-12-23 13:35:43

标签: objective-c cocoa quartz-graphics nsview

我有一个NSView,我绘制了数千个NSBezierPaths。我想在mousemoved事件中突出显示(更改填充颜色)选定的一个。目前我在mouseMoved函数中使用以下命令:

     [self setsetNeedsDisplay:YES];

强制调用drawRect重绘每个路径。我想只重绘选定的一个。 我试图在drawRect函数中使用addClip:

      NSBezierPath * path = ... //builds the path here
      [path addClip];
      [path fill];

但似乎drawRect会破坏所有其他先前绘制的路径并仅重绘剪裁的路径。

调用drawRect时是否可以不使所有视图无效?我的意思是只是逐步覆盖之前视图上的内容?

谢谢, 卢卡

2 个答案:

答案 0 :(得分:4)

您应该使用[self setNeedsDisplayInRect:…]。传递您想要失效的NSRect,这将是传递给drawRect:电话的区域。

drawRect:内,检查传入的区域,仅在该矩形内执行必要的绘图。

此外,您可能希望使用NSTrackingArea代替mouseMoved: - 这些允许您设置特定的矩形来触发更新。

答案 1 :(得分:1)

我认为我以更快的方式解决了,因为我不知道哪个路径存在于矩形中我想避免循环遍历所有路径。幸运的是,我的路径不会经常更改,因此我可以缓存NSImage中的所有路径。在mouseMoved事件中,我设置了:

RefreshAfterMouseMoved = YES;

在drawRect函数中我输入了类似的东西:

if (RefreshAfterMouseMoved) {       
    [cacheImage drawAtPoint:zero fromRect:viewRect operation:1 
                       fraction:(CGFloat)1.0];
        //redraw only the hilighted path
}
else{
    if (cacheImage) [cacheImage release];   
    cacheImage = [[NSImage alloc] initWithSize: [self bounds].size ];
    [cacheImage lockFocus];
    // draw everything here
    [cacheImage unlockFocus];
    [cacheImage drawAtPoint:zero fromRect:viewRect operation:1 
                   fraction:(CGFloat)1.0];
}

此方法可以与上面的setNeedsDisplayInRect方法结合使用mousedMoved函数:

   NSRect a, b, ab;
   a = [oldpath bounds];
   b = [newpath bounds];
   ab = NSUnionRect(a,b);
   RefreshAfterMouseMoved = YES;
   [self setNeedsDisplayInRect:ab];