通过子类化NSView来实现透明背景

14

我正在创建一个应用程序,其中需要一个带有透明PNG图像的透明NSView。问题是,我正在绘制的NSView具有灰色背景。我已经将其子类化(作为TransparentRectangleView),但不知道在drawRect中放什么来使其透明。

我已经覆盖了isOpaque方法以返回NO,但似乎没有帮助......

或者,是否已经存在一个类似于iPhone的UIImageView的子类化NSView(只要我可以在其中添加子视图,我需要在其中添加一些文本)。


1
在Interface Builder中没有透明度滑块吗?我记得我曾经意外地降低了一个视图的不透明度。 - Sam Dufel
1
我几乎可以确定这将设置整个视图的透明度,包括子元素。这意味着我的所有按钮和文本也将具有1%的不透明度或其他值。如果我错了,请告诉我:D - Andrew M
1
等一下,所以你只是想要一个透明的背景颜色吗?我知道对于UIView,有一个预定义的透明颜色可以使用,尽管我没有尝试过在NSViews中使用它。 - Sam Dufel
是的,我用的是Mac,所以UIView和NSView不一样。无论如何,我用FakeImageView解决了这个问题。 - Andrew M
@Andrew M,你错了,一个视图的透明度不会影响它的子视图。视图是独立绘制的。 - d11wtq
3个回答

21

为了使视图透明,只需用 [NSColor clearColor] 填充它即可。

- (void)drawRect:(NSRect)rect {
    [[NSColor clearColor] set];
    NSRectFill(rect);
}

isOpaque的默认实现返回NO,所以如果你正在子类化NSView而不是其他视图,你不需要担心覆盖它。


这对未来非常有用!谢谢! - Andrew M
4
顺便提一下,我相当确定如果你将drawRect:保留为空,则可以获得相同的效果,因为你不会画任何东西。 相当确定=确定,因为我经常这样做。 - d11wtq
除非您将窗口设置为非不透明(窗口而非视图!NSView默认情况下是非不透明的,但NSWindow默认情况下是不透明的),否则您的代码会绘制一个黑色矩形。请参见此文本http://www.drissman.com/blog/archives/2009/10/09/nsrectfill_and_nscolor_clearcolor.html。因此,您要么想提到窗口的这一点,要么像文本中所示使用NSRectFillUsingOperation。哦,在视图被分层的情况下,它也可以工作,因为在这种情况下它有自己的绘图层。 - Mecki
@Mecki,原帖似乎并不是在询问如何使整个窗口透明,而是只想让视图透明,以便您可以在其下看到其他视图。 - ughoavgfhw
@ughoavgfhw 你似乎不理解:除非窗口设置为非透明,否则你的代码会绘制黑色。无论 OP 是否想要一个非透明的窗口,你的代码只能在非透明的窗口上工作。你有没有真正尝试过你的代码? - Mecki
将代码 http://rextester.com/SHLGC62567 复制到 main.m,使用 clang -framework Cocoa -o windowtest main.m 进行编译,并使用 ./windowtest 运行。这是输出的样子:https://s29.postimg.org/6a4mv566f/so_4635442.png 窗口左上角看起来像有一个透明的 NSView 吗?不是的。但这正是你的代码在非不透明窗口上所做的事情,除非内容视图是分层的(默认情况下它不是)。 - Mecki

11

1
对于大多数内容,SourceOver是默认的合成操作。这与[NSBezierPath fillRect:]没有什么不同,并且比NSRectFill效率和效果都差一些,后者(不寻常地)使用了“ NSCopyCompositeOperation”。正如d11wtq在被接受的答案中所说,这也不是必要的-视图本身已经是透明的,除非你另外绘制。 - Peter Hosey
@PeterHosey,你有没有读链接中的文本?不,它们不一样。使用透明颜色的NSRectFill仅在窗口未被显式设置为非不透明时才有效,当然你可以这样做,但如果你的窗口实际上是不透明的,那么这将浪费大量计算时间。NSRectFillUsingOperation将正确工作,无论窗口是否不透明。链接中的文本非常好地解释了这一点,并帮我省了很多工作。 - Mecki

8

Swift版本:

override func draw(_ dirtyRect: NSRect) {

    NSColor.clear.set()
    dirtyRect.fill()
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接