【问题标题】:How to update a section of an NSView without redrawing the whole view如何在不重绘整个视图的情况下更新 NSView 的一部分
【发布时间】: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时是否可以不使所有视图无效?我的意思是逐步覆盖之前的视图?

谢谢, 卢卡

【问题讨论】:

    标签: objective-c cocoa quartz-graphics nsview


    【解决方案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];
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-20
      • 2019-03-15
      • 2015-10-27
      • 1970-01-01
      • 2011-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多