是否可以切割NSWindow或NSView的某些部分,使它们变成透明的? 我有一个带有NSView的NSWindow,我想要:
A)在NSWindow中打一个洞,以便能够透过它看到外面
B)将我的NSWindow背景设置为透明色,然后在上面放置一个NSView,并将NSView的某个部分的不透明度设置为透明以便能够透过去看到桌面。
这是我试图创建的效果:
是否可以切割NSWindow或NSView的某些部分,使它们变成透明的? 我有一个带有NSView的NSWindow,我想要:
A)在NSWindow中打一个洞,以便能够透过它看到外面
B)将我的NSWindow背景设置为透明色,然后在上面放置一个NSView,并将NSView的某个部分的不透明度设置为透明以便能够透过去看到桌面。
这是我试图创建的效果:
是的,这是可能的,而且实际上并不难。
在您的窗口子类中,您需要将窗口背景颜色设置为透明。
self.backgroundColor = NSColor.clearColor;
告诉合成引擎您窗口的某些部分是透明的,当窗口移动时需要重新绘制
[self setOpaque:NO];
在早期版本的macOS中,设置背景色并不是必要的,而且许多答案仍然没有提到这一事实。但我已经验证,至少在macOS 10.11及以后版本中是必要的。
在您的NSView子类中,您必须使用您选择的颜色来渲染新的背景(否则窗口完全透明,只会显示标题栏),然后用
NSRectFillUsingOperation(NSMakeRect(50, 50, 100, 100), NSCompositingOperationClear);
这样做可以得到期望的效果,并且在Mojave的暗模式下也适用。
完整代码:
@interface MyWindow : NSWindow
- (id)initWithContentRect:(NSRect)contentRect styleMask:( unsigned int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag;
@end
@implementation MyWindow
- (id)initWithContentRect:(NSRect)contentRect styleMask:( unsigned int)aStyle backing:(NSBackingStoreType)bufferingType defer:(BOOL)flag {
self = [super initWithContentRect:contentRect styleMask : aStyle backing :bufferingType defer:flag ];
if (self)
{
self.backgroundColor = NSColor.clearColor;
[self setOpaque:NO];
[self setHasShadow:NO];
}
return self;
}
@end
@interface MyView : NSView
- (void)drawRect:(NSRect)rect;
@end
@implementation MyView
- (void)drawRect:(NSRect)rect
{
[[NSColor windowBackgroundColor] set];
NSRectFill(self.bounds);
NSRectFillUsingOperation(NSMakeRect(50, 50, 100, 100), NSCompositingOperationClear);
}
@end
NSCompositeClear
不会穿透子视图进行绘制。然而,在子视图的绘制代码中使用NSCompositeClear
将会穿透其父视图进行绘制。 - spudwaffleMyWindow
上错过了 hasShadow
。这就是解决我的所有问题的方法。(当时我并不关心阴影。) 看起来 MyView.drawRect
只是在第一次绘制时穿过。当我在其他地方重新绘制孔时,后备窗口似乎没有更新孔。切换可以解决问题。谢谢! - waggles