drawInRect for Mac App之前清除

时间:2013-02-19 23:47:58

标签: objective-c xcode macos nsimage

我想在Mac App中为我的按钮的宽度设置动画,同时拥有背景图像和前景图像。为此,我正在使用@ kgn的真棒库BBlock(https://github.com/kgn/BBlock)。

问题是背景图像似乎相互拉开,所以当按钮缩小时,你甚至看不到背景图像动画,它似乎被切断了。 Button Image Cut Off

如果我只使用setImage,这种“动画化”宽度变化的方式有效,但是我没有得到背景图像的好处。

我已经制作了一个自定义按钮,可以递增地缩放按钮(基本上是为它设置动画)。它会将每个按钮的按钮大小更改一个像素,并将图像,背景图像和备用背景图像也改变一个像素:

- (void)scaleTestButtonUntilWidth:(int)width{
    [NSTimer scheduledTimerRepeats:YES withTimeInterval:timeInterval andBlock:^{
        if (self.width == width) {
            return;
        }

        int newSize;
        if (width > self.width) {
            newSize = self.width += 1;
        }else if (width < self.width){
            newSize = self.width -= 1;
        }

        self.width = newSize;
        [self setImage:self.image];
        [self setAlternateBackgroundImage:[self alternateBGImage]];
        [self setBackgroundImage:[self BGImage]];
    }];
}

setBackgroundImage看起来像这样,setAlternateBackgroundImage的实现是相同的:

- (void)setBackgroundImage:(NSImage *)backgroundImage{
    [self setImage:[self imageWithBackgroundImage:backgroundImage
                                          andIcon:self.image]];
    [self setButtonType:NSMomentaryChangeButton];
    [self setBordered:NO];
}

调用实际绘制图像的方法:

- (NSImage *)imageWithBackgroundImage:(NSImage *)background andIcon:(NSImage *)icon{
    return [NSImage imageForSize:background.size withDrawingBlock:^{
        NSRect bounds = NSZeroRect;
        bounds.size = background.size;

        NSRect iconRect = NSZeroRect;
        iconRect.size = icon.size;
        iconRect.origin.x = round(background.size.width*0.5f-iconRect.size.width*0.5f);
        iconRect.origin.y = round(background.size.height*0.5f-iconRect.size.height*0.5f);

        [background drawInRect:bounds fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
        [icon drawInRect:iconRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
    }];
} 

借助此方法:

+ (NSImage *)imageForSize:(NSSize)size withDrawingBlock:(void(^)())drawingBlock{
    if(size.width <= 0 || size.width <= 0){
        return nil;
    }

    NSImage *image = [[NSImage alloc] initWithSize:size];

    [image lockFocus];
    drawingBlock();
    [image unlockFocus];
#if !__has_feature(objc_arc)
    return [image autorelease];
#else
    return image;
#endif
}

2 个答案:

答案 0 :(得分:0)

也许尝试保存并恢复图形上下文。

return [NSImage imageForSize:background.size withDrawingBlock:^{
    NSRect bounds = NSZeroRect;
    bounds.size = background.size;

    NSRect iconRect = NSZeroRect;
    iconRect.size = icon.size;
    iconRect.origin.x = round(background.size.width*0.5f-iconRect.size.width*0.5f);
    iconRect.origin.y = round(background.size.height*0.5f-iconRect.size.height*0.5f);

    CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
    CGContextSaveGState(context);        
    [background drawInRect:bounds fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
    [icon drawInRect:iconRect fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0f];
    CGContextRestoreGState(context);
}];

答案 1 :(得分:0)

我想知道你是否会更好地继承NSButton并覆盖drawRect