绘制成透明叠加子视图NSView

时间:2012-01-08 19:06:56

标签: macos cocoa

我在Mac OS X 10.6问题上有一个相对简单的Cocoa要问。我有一个主NSView(实际上是ScreensaverView),它不是图层支持的,否则就不起眼了。它通过drawRect通过NSRectFillNSBezierPath:stroke调用(基本上是点和线)来完成一些基本绘图。

我还有一个NSView派生的子类,它充当子子视图。我这样做的目的是在子视图中绘制简单的线条,绘制在主视图中绘制的任何内容之上,但随后可以以某种方式“擦除”显示任何线条遮挡。这个子视图的代码非常简单:

- (id)initWithFrame:(NSRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code here.
    }
    return self;
}

- (void)dealloc
{   
    [super dealloc];
}

- (void)drawRect:(NSRect)dirtyRect {

    // Transparent background
    [[NSColor clearColor] set];
    NSRectFillUsingOperation(dirtyRect, NSCompositeCopy);

    // If needed for this update, draw line
    if (drawLine) {
        // OMITTED: Code that sets opaque NSColor and draws a line using NSBezierPath:stroke
    }

    // If needed for this update, "erase" line
    if (eraseLine) {
        [[NSColor blackColor] set]; // clearColor?
        // OMITTED: Code that draws the same line using NSBezierPath:stroke
    }
}

使用上面显示的代码,只要子视图绘制,主视图就会变黑,您只能看到子视图行。未更新子视图时,主视图内容将再次出现。

我尝试过的事情,结果各不相同:

  • 我尝试尝试让子视图从被覆盖的YES返回isOpaque(我意识到这不是真的正确)。当我这样做时,两个视图在子视图更新期间正确绘制,但是子视图行会覆盖它所绘制的任何内容(确定),然后在删除时,也会留下一条大黑线(我试图避免的)。尝试使用clearColor代替blackColor“删除”该行会导致该行保留在屏幕上。

  • 我尝试通过调用[self setWantsLayer:YES]中的init同时制作两个(和/或只是子视图)图层支持的视图,这会导致完全黑屏。

我觉得我错过了一些非常基本的东西,但不管出于什么原因,我似乎无法弄明白。非常感谢任何和所有建议。

1 个答案:

答案 0 :(得分:2)

我认为你从根本上误解了视图的工作原理。基本上,每次在视图上调用drawRect:时,都会执行drawRect:中的绘图命令。这可能会自动发生,也可能在您发出setNeedsDisplay:消息时发生。

通常,在视图上调用drawRect:时,视图将被删除并重新开始绘制。之前对drawRect:的调用在视图中没有任何内容。您无需使用[NSColor clearColor]填充视图,以使其透明。

请注意,只有当您的视图从NO返回isOpaque时才会出现这种情况,这是默认设置。如果您的观点从YES返回isOpaque,那么您需要确保在绘制前删除视图,但在特定情况下,您不应该从YES返回isOpaque因为你希望你的观点是透明的。

您无需“擦除”您绘制的线条。它会被删除。相反,当你不想绘制它时,你需要简单地不绘制它。

基本上,您的视图应该存储一些标记(例如名为BOOL的{​​{1}} ivar或类似的东西。然后,在您的绘图代码中,您应该只检查是否设置了此值。如果是,你应该画线。如果没有,那就什么都不做。您的代码应该简化为:

drawLine

如果您想更改状态并重绘视图,您只需更改- (void)drawRect:(NSRect)rect { // If needed for this update, draw line if (drawLine) { // OMITTED: Code that sets opaque NSColor and draws a line using NSBezierPath:stroke } } ivar的值并使用drawLine要求视图重绘。

您可以使用计时器轻松完成此操作:

[yourView setNeedsDisplay:YES]