在NSView中重复背景图片

8
我正在尝试在我的NSView中绘制一个重复的背景图片,目前我有以下代码:
// INIT
- (id)initWithFrame:(NSRect)frame {
  if (self = [super initWithFrame:frame]) {
    self.backgroundImage = [NSImage imageNamed:@"progressBackground.pdf"];
  }

  return self;
}

// DRAW
- (void)drawRect:(NSRect)dirtyRect {
  // Draw the background
  [backgroundImage drawInRect:[self bounds]
                     fromRect:NSMakeRect(0.0f, 0.0f, backgroundImage.size.width, backgroundImage.size.height)
                    operation:NSCompositeSourceAtop
                     fraction:1.0f];
  NSLog(@"%dx%d", backgroundImage.size.width, backgroundImage.size.height);
}

然而,该视图将图像拉伸以填充自身。我希望图像重复出现。
此外,一些奇怪的事情发生了,控制台显示图像的大小为-2109897792x0,但实际上图像的大小是32x32! 真是令人困惑!
有人能帮我吗?谢谢。

2
可能不是一个好主意去威胁对于与问题无关的回答进行投票否决。这种做法往往会让人们失去兴趣甚至不再费心回答。 - Joshua Nozzi
2
@Joshua,但是收到关于错误平台的答案非常非常令人恼火。 - user142019
当然你能看出在任何人做错事之前警告他们和因为实际违规行为而这样做的区别。前者最多是不友好的;后者更加值得。 - Joshua Nozzi
3
你看到"-2109897792x0"是因为backgroundImage.size.width是一个CGFloat类型,而你在格式字符串中传递了%d,表明参数将是一个整数。我会建议你修改格式字符串,使用%f来代替%d来匹配CGFloat类型的参数。 - Jon Hess
3个回答

22
你可以使用+[NSColor colorWithPatternImage:]创建一个图案颜色,然后只需用该“颜色”填充背景矩形。这样就能实现你想要的效果了。

2
请注意,这是相对于窗口底部的位置(根据文档)。当调整窗口大小时(视图随之调整大小),图案的左上角点将会移动(导致背景在您的图案视图的任何子视图后面“游动”)。这可能会令人恶心。 :-) - Joshua Nozzi
3
我知道这篇帖子已经很旧了,但我也遇到了完全相同的问题。是否可以将“backgroundimage”固定在顶部? - ovm

17
我在这里找到了答案,可以防止图案从底部绘制并在窗口调整大小时产生奇怪的效果:

http://www.mere-mortal-software.com/blog/details.php?d=2007-01-08

基本上,你只需要在drawRect中保存你的图形上下文状态,调用该方法,绘制你的图案,然后恢复你的状态。 这个方法是:
- (void)drawRect:(NSRect)dirtyRect {
    NSGraphicsContext* theContext = [NSGraphicsContext currentContext];
    [theContext saveGraphicsState];
    [[NSGraphicsContext currentContext] setPatternPhase:NSMakePoint(0,[self frame].size.height)];
    [self.customBackgroundColour set];
    NSRectFill([self bounds]);
    [theContext restoreGraphicsState]; 
}

我在init方法中初始化了背景色模式:

- (id)initWithFrame:(NSRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.customBackgroundColour = [NSColor colorWithPatternImage:[NSImage imageNamed:@"light-linen-texture.png"]];
    }

    return self;
}

1
将一些关键词添加到帮助他人查找此内容:将图像视图固定在顶部/顶部固定。 - ecume des jours
有人知道是什么原因导致这样的代码仍然会拉伸图案而不是平铺吗?我注意到我的drawRect在视图调整大小时没有被调用,也许这与此有关? - Pierre Houston
在上面的评论中回答了自己的问题:每当视图框架改变时,我必须将视图集设置为needsDisplay为YES,并覆盖setFrame本身以执行此操作。我不确定这是否是正常的做法,或者是否有类似于CALayer的needsDisplayOnBoundsChange的内置机制,但它正在工作。 - Pierre Houston

0

在Github上查看RMSkinnedView!

编辑:RMSkinnedView是一个NSView子类,您可以通过接口生成器中的用户定义的运行时属性直接设置多个选项,包括圆角、背景颜色、背景图案等。


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