当窗口改变大小时,带有填充(图案图像)的NSView会滚动

时间:2023-01-24 08:55:02

I have an NSView with a drawRect

我有一个带有drawRect的NSView

- (void)drawRect:(CGRect)rect {
    // Drawing code
    NSPoint origin = [self visibleRect].origin;
    [[NSGraphicsContext currentContext]
     setPatternPhase:NSMakePoint(origin.x, origin.y)];
    [[NSColor colorWithPatternImage: self.image] set];
    [NSBezierPath fillRect: [self bounds]];
}

It draws my pattern perfectly, but i can see the pattern scroll when i change the the size of my window.

它完美地绘制了我的图案,但是当我改变窗口的大小时,我可以看到图案滚动。

i have tried to set the view isFlipped to YES but that doesn't change anything.

我试图将视图isFlipped设置为YES,但这不会改变任何东西。

2 个解决方案

#1


1  

You need to do some off-screen drawing first and then draw that result onto the view. For example you can use a blank NSImage of the exact same size as the view, draw the pattern on that image and then draw that image on the view.

您需要先进行一些离屏绘制,然后将该结果绘制到视图上。例如,您可以使用与视图完全相同大小的空白NSImage,在该图像上绘制图案,然后在视图上绘制该图像。

Your code may look something like that:

您的代码可能看起来像这样:

- (void)drawRect:(NSRect)dirtyRect
{
  // call super
  [super drawRect:dirtyRect];

  // create blank image and lock drawing on it    
  NSImage* bigImage = [[[NSImage alloc] initWithSize:self.bounds.size] autorelease];
  [bigImage lockFocus];

  // draw your image patter on the new blank image
  NSColor* backgroundColor = [NSColor colorWithPatternImage:bgImage];
  [backgroundColor set];
  NSRectFill(self.bounds);

  [bigImage unlockFocus];

  // draw your new image    
  [bigImage drawInRect:self.bounds
            fromRect:NSZeroRect 
           operation:NSCompositeSourceOver 
            fraction:1.0f];
}

// I think you may also need to flip your view
- (BOOL)isFlipped
{
  return YES;
}

#2


0  

Swift

A lot has changed, now things are easier, unfortunately part of objective-C's patrimony is lost and when it comes to Cocoa, Swift is like an orphan child. Anyways, based on Neovibrant's we can deduct the solution.

很多事情发生了变化,现在事情变得更容易了,不幸的是,客观的一部分 - C的遗产已经丢失,而当谈到Cocoa时,Swift就像一个孤儿。无论如何,基于Neovibrant,我们可以扣除解决方案。

  1. Subclass NSView
  2. Override draw method
    • Call parent method (this is important)
    • 调用父方法(这很重要)

    • Set a fill on buffer within the bounds of the view
    • 在视图的边界内设置填充缓冲区

    • Draw fill on buffer
    • 在缓冲区上绘制填充

  3. 覆盖draw方法调用父方法(这很重要)在视图的边界内设置填充缓冲区

code

    override func draw(_ dirtyRect: NSRect) {
         super.draw(dirtyRect)

         let bgimage : NSImage = /* Set the image you want */
         let background = NSColor.init(patternImage: bgimage)
         background.setFill()

         bgimage.draw(in: self.bounds, from: NSZeroRect, operation: .sourceOver, fraction: 1.0)
    }

#1


1  

You need to do some off-screen drawing first and then draw that result onto the view. For example you can use a blank NSImage of the exact same size as the view, draw the pattern on that image and then draw that image on the view.

您需要先进行一些离屏绘制,然后将该结果绘制到视图上。例如,您可以使用与视图完全相同大小的空白NSImage,在该图像上绘制图案,然后在视图上绘制该图像。

Your code may look something like that:

您的代码可能看起来像这样:

- (void)drawRect:(NSRect)dirtyRect
{
  // call super
  [super drawRect:dirtyRect];

  // create blank image and lock drawing on it    
  NSImage* bigImage = [[[NSImage alloc] initWithSize:self.bounds.size] autorelease];
  [bigImage lockFocus];

  // draw your image patter on the new blank image
  NSColor* backgroundColor = [NSColor colorWithPatternImage:bgImage];
  [backgroundColor set];
  NSRectFill(self.bounds);

  [bigImage unlockFocus];

  // draw your new image    
  [bigImage drawInRect:self.bounds
            fromRect:NSZeroRect 
           operation:NSCompositeSourceOver 
            fraction:1.0f];
}

// I think you may also need to flip your view
- (BOOL)isFlipped
{
  return YES;
}

#2


0  

Swift

A lot has changed, now things are easier, unfortunately part of objective-C's patrimony is lost and when it comes to Cocoa, Swift is like an orphan child. Anyways, based on Neovibrant's we can deduct the solution.

很多事情发生了变化,现在事情变得更容易了,不幸的是,客观的一部分 - C的遗产已经丢失,而当谈到Cocoa时,Swift就像一个孤儿。无论如何,基于Neovibrant,我们可以扣除解决方案。

  1. Subclass NSView
  2. Override draw method
    • Call parent method (this is important)
    • 调用父方法(这很重要)

    • Set a fill on buffer within the bounds of the view
    • 在视图的边界内设置填充缓冲区

    • Draw fill on buffer
    • 在缓冲区上绘制填充

  3. 覆盖draw方法调用父方法(这很重要)在视图的边界内设置填充缓冲区

code

    override func draw(_ dirtyRect: NSRect) {
         super.draw(dirtyRect)

         let bgimage : NSImage = /* Set the image you want */
         let background = NSColor.init(patternImage: bgimage)
         background.setFill()

         bgimage.draw(in: self.bounds, from: NSZeroRect, operation: .sourceOver, fraction: 1.0)
    }