背景问题:NSView上的NSButton

时间:2014-03-29 09:33:39

标签: cocoa drawing nsbutton

我有一个带有自定义视图的窗口。这个视图得到的图像是作为背景绘制的。我们现在假设它是一个结构化的灰色背景图像。

- (void)drawRect:(NSRect)dirtyRect
{
    [super drawRect:dirtyRect];
    [self.titlebarBGImage drawInRect:dirtyRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
}

在这个自定义视图中,我添加了一个方形纹理按钮,并在IB中配置它没有边框。在我的AppDelegate中,然后在applicationDidFinishLaunching方法中为此按钮提供一个图像:

// ...
// [[self.minimizeButton cell] setBackgroundColor:[NSColor clearColor]];
[self.minimizeButton setImage:minimizeImage];
// ...

不知何故,相同的背景(titlebarBGImage)也被绘制为按钮背景,因此它具有结构化的灰色图像,但缩放以适合按钮大小。这看起来很傻,显然不是我想要的。如果我然后取消注释与setBackgroundColor:的行,背景被清除,但自定义视图背景也没有透过按钮图像透明的位置(按钮图像是一个圆圈)所以我得到一个矩形窗口背景闪耀(即示例图像中的绿色),而不是按钮所在视图的背景。

这是一张图片,可以清楚地说明会发生什么:

enter image description here

从上到下:

  • 我想要实现的目标,即视图灰色结构化bg通过按钮透明区域
  • 闪耀
  • 我用上面的代码得到的,即没有未注释的行:自定义视图背景被绘制到按钮背景中
  • 我使用clearColor行获得的内容,即窗口颜色(绿色)透过,而不是视图的bg。

如何获得最高结果?

编辑:我推了一个example project to github,以便你可以看到我的意思。

1 个答案:

答案 0 :(得分:0)

解决此问题的一种方法是使用核心动画层。我发现了this tutorial。为此,您需要访问MainMenu.xib文件,选择Button对象并单击Utilities中的layers选项卡(参见屏幕截图(1))。然后为最顶层的View激活核心动画层。所有子元素都激活了核心动画层(如果项目更大,可能存在性能问题,请注意)。

How to activate Core Animation Layer

接下来,我将NSButton子类化(在我的Github项目中调用它BPButtonView,我现在更新了)。选择xib文件中的Button,然后将 Custom Class 更改为BPButtonView,或者您调用的任何内容。

Don't forget to set the buttons correct class name in the Utilities sidebar

新NSButton子类的代码如下所示:

@implementation BPButtonView

- (BOOL)wantsUpdateLayer {
    return YES;
}

- (void)updateLayer {
    if ( [self.cell isHighlighted] ) {
        self.layer.contents = [NSImage imageNamed:@"buttonbg.png"];
    } else {
        self.layer.contents = [NSImage imageNamed:@"buttonbg.png"];
    }
}

@end

我在updateLayer方法中使用if语句只是为了显示,根据按钮状态(按下与未按下),您可以提供不同的图片。在视频教程中,还有一个很好的技巧,如何实现按钮图片的干净调整大小。

这是生成的应用程序的屏幕截图。中间的红色圆圈是按钮,绿色纹理的东西是视图背景。

Resulting App with NSView background and a button placed in this view