如何在不重绘整个视图的情况下更新 NSView 的一部分
Posted
技术标签:
【中文标题】如何在不重绘整个视图的情况下更新 NSView 的一部分【英文标题】:How to update a section of an NSView without redrawing the whole view 【发布时间】:2009-12-23 13:35:42 【问题描述】:我有一个 NSView,我在其中绘制了数千个 NSBezierPath。我想在 mousemoved 事件中突出显示(更改填充颜色)选定的一个。目前我在 mouseMoved 函数中使用以下命令:
[self setsetNeedsDisplay:YES];
强制调用 drawRect 来重绘每个路径。我想只重绘选定的一个。 我尝试在 drawRect 函数中使用 addClip:
NSBezierPath * path = ... //builds the path here
[path addClip];
[path fill];
但似乎 drawRect 会破坏所有其他先前绘制的路径并仅重绘被剪裁的路径。
调用drawRect时是否可以不使所有视图无效?我的意思是逐步覆盖之前的视图?
谢谢, 卢卡
【问题讨论】:
【参考方案1】:您应该使用[self setNeedsDisplayInRect:…]
。传递您想要失效的 NSRect,这将是传递给 drawRect:
调用的区域。
在drawRect:
内,检查传入的区域,只在该矩形内执行必要的绘制。
此外,您可能想考虑使用 NSTrackingArea
而不是 mouseMoved:
- 这些允许您设置特定的矩形来触发更新。
【讨论】:
嗨,好的,我可以传递类似:[self setNeedsDisplayInRect: [path bounds]]... 即使它不是很舒服,因为我不知道那个 NSRect 上有多少路径...但我可以尝试重新考虑该功能。相反,我如何利用 NSTrackingArea 并不是很清楚。目前我已经有了一个覆盖整个 NSView 的 trackingarea,但是我认为生成的事件仍然发送到 mouseMoved 函数,不是吗?谢谢,卢卡 您的mouseMoved:
方法将由NSEvent
实例触发,您向事件发送-trackingArea
消息以获取对触发它的NSTrackingArea
实例的引用,然后询问它的矩形。【参考方案2】:
我认为我以更快的方式解决了问题,因为我不知道矩形中存在哪些路径我想避免通过所有路径循环。幸运的是,我的路径不会经常更改,因此我可以将所有路径缓存在 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];
【讨论】:
以上是关于如何在不重绘整个视图的情况下更新 NSView 的一部分的主要内容,如果未能解决你的问题,请参考以下文章