在 NSView 中绘制图像

发布于 2024-07-30 17:16:50 字数 2291 浏览 4 评论 0原文

我有一个简单的 Obj C 程序,目前可以让您加载图像、绘制图像,并且理论上应该可以让您缩放和旋转。 我正在使用 NSAffineTranslations。

我希望图像锁定在左上角(与左下角的 PS/PDF 标准相反),所以我使用 isFlipped,并调用 [afTrans scaleXBy:1.0 yBy:-1.0];

问题是,由于某种原因,第一次调用我的drawRect后,转换没有发生。

当我加载图像时,它会出现,并且看起来正确。 如果我改变窗口的大小(调用drawRect),图像就会绘制,但会上下颠倒。 这意味着转变没有生效。 第二次查看时,我没有发现任何数据有任何差异。

这是代码的精简版本:

- (void)drawRect:(NSRect)rect 
{
    // Drawing code here.

//    NSLog(@"window type: %d", [[self window] backingType]);
   NSAffineTransform *afTrans = [[NSAffineTransform alloc] init];
   NSGraphicsContext *context = [NSGraphicsContext currentContext];
   NSSize sz;
   NSRect windowFrame = [[self window] frame];
   NSRect cv =[[[self window] contentView] frame];
   float deltaX, deltaY;
   NSSize superSize = [[self superview] frame].size;
   float height, width, sHeight, sWidth;

   NSRect imageRect;

   sz = [ image size];
   imageRect.size = sz;
   imageRect.origin = NSZeroPoint;

   height = sz.height  ;
   width = sz.width  ;

//    sHeight and sWidth are the hieght and with of the super-view. ie,
//    the size of the whole window view including the space for the
//    scroll bars, etc, but not including the panel or the borders,
   sHeight = superSize.height;
   sWidth = superSize.width;

   [context saveGraphicsState];

   deltaX = 0;
   deltaY = 0;

   deltaY += height; // account for flipping

   [afTrans translateXBy:deltaX yBy:deltaY];

   [afTrans scaleXBy:1.0 yBy:-1.0];

   [afTrans concat];

   NSRect drawingRect = imageRect;
   NSRect frame = imageRect;
   [self setFrame:frame];

   [image drawInRect:drawingRect
         fromRect:imageRect
         operation:NSCompositeSourceOver
         fraction:1];

   [afTrans release];
   [context restoreGraphicsState];
}

ETA:这里还有一些可能相关的代码。

-(void )setImage:( NSImage * )newImage
{
    [newImage retain];
    [image release];

    rotation = 0;

    zoom = 1.0;

    image = newImage;
    NSSize imageSize = [newImage size];
    NSRect tFrame = [self frame];
    tFrame = [[self window] frame];

    tFrame.size.width = MAX(tFrame.size.width, imageSize.width);
    tFrame.size.height = MAX(tFrame.size.height, imageSize.height);
    [self setFrame:tFrame];

    [self setNeedsDisplay:YES];
}

I have a simple Obj C program that, at the moment, lets you load an image, draws it up, and theoretically should let you zoom and rotate. I'm using NSAffineTranslations.

I want the image to be locked to the upper left (As opposed to the PS/PDF standard of lower left), so I'm using isFlipped, and calling [afTrans scaleXBy:1.0 yBy:-1.0];

The problem is that for some reason, after the first time my drawRect is called, the transformation doesn't happen.

When I load an image, it comes up, and looks correct. If I change the size of the window (Which calls drawRect), the image draws, but is upside-down and reversed. This means that the transformation didn't take effect. I don't see any differences in any of the data the 2nd time through.

here is a stripped down version of the code:

- (void)drawRect:(NSRect)rect 
{
    // Drawing code here.

//    NSLog(@"window type: %d", [[self window] backingType]);
   NSAffineTransform *afTrans = [[NSAffineTransform alloc] init];
   NSGraphicsContext *context = [NSGraphicsContext currentContext];
   NSSize sz;
   NSRect windowFrame = [[self window] frame];
   NSRect cv =[[[self window] contentView] frame];
   float deltaX, deltaY;
   NSSize superSize = [[self superview] frame].size;
   float height, width, sHeight, sWidth;

   NSRect imageRect;

   sz = [ image size];
   imageRect.size = sz;
   imageRect.origin = NSZeroPoint;

   height = sz.height  ;
   width = sz.width  ;

//    sHeight and sWidth are the hieght and with of the super-view. ie,
//    the size of the whole window view including the space for the
//    scroll bars, etc, but not including the panel or the borders,
   sHeight = superSize.height;
   sWidth = superSize.width;

   [context saveGraphicsState];

   deltaX = 0;
   deltaY = 0;

   deltaY += height; // account for flipping

   [afTrans translateXBy:deltaX yBy:deltaY];

   [afTrans scaleXBy:1.0 yBy:-1.0];

   [afTrans concat];

   NSRect drawingRect = imageRect;
   NSRect frame = imageRect;
   [self setFrame:frame];

   [image drawInRect:drawingRect
         fromRect:imageRect
         operation:NSCompositeSourceOver
         fraction:1];

   [afTrans release];
   [context restoreGraphicsState];
}

ETA: here's some more code that MIGHT be relevant.

-(void )setImage:( NSImage * )newImage
{
    [newImage retain];
    [image release];

    rotation = 0;

    zoom = 1.0;

    image = newImage;
    NSSize imageSize = [newImage size];
    NSRect tFrame = [self frame];
    tFrame = [[self window] frame];

    tFrame.size.width = MAX(tFrame.size.width, imageSize.width);
    tFrame.size.height = MAX(tFrame.size.height, imageSize.height);
    [self setFrame:tFrame];

    [self setNeedsDisplay:YES];
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

掐死时间 2024-08-06 17:16:50

我不确定你到底想要实现什么,但是如果你只想在 NSView 中绘制图像并将其保留在左上角,你可以在你的 NSView 子类中做一些更简单的事情:

- (BOOL)isFlipped
{
    return YES;
}

- (void)setImage:(NSImage *)newImage
{
    [newImage retain];
    [image release];
    image = newImage;

    [image setFlipped:YES];
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect
{
    [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];

    // Or stretch image to fill view
    //[image drawInRect:[self bounds] fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
}

我也是通过消除 drawRect 和 setImage 方法中的 [self setFrame:...]; 调用,您可以使用代码获得类似的结果。

I'm not sure exactly what you're trying to achieve, but if you want to just draw an image in a NSView and keep it in the upper left, you can do something a bit simpler, in your NSView subclass:

- (BOOL)isFlipped
{
    return YES;
}

- (void)setImage:(NSImage *)newImage
{
    [newImage retain];
    [image release];
    image = newImage;

    [image setFlipped:YES];
    [self setNeedsDisplay:YES];
}

- (void)drawRect:(NSRect)rect
{
    [image drawAtPoint:NSZeroPoint fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];

    // Or stretch image to fill view
    //[image drawInRect:[self bounds] fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1];
}

I was also able to get similar results with your code by getting rid of the [self setFrame:...]; calls in drawRect and setImage methods.

十雾 2024-08-06 17:16:50

假设您没有删除更改内容的代码,请注意您是否在其他地方绘制图像。 工具栏项、表格等很可能会更改图像的 -flipped 属性,导致其绘制不正确。

在您的图像绘制线周围尝试一下:

BOOL wasFlipped = [image isFlipped];
[image setFlipped:[self isFlipped]];
[image drawInRect:drawingRect
             fromRect:imageRect
            operation:NSCompositeSourceOver
             fraction:1];
[image setFlipped:wasFlipped];

看看是否有帮助。 如果确实如此,请在代码中的其他位置查找更改图像翻转属性而不是将其放回原处的内容。

Assuming you're not stripping out code that changes stuff, watch out if you're drawing the image elsewhere. Toolbar items, tables and so on may well change the -flipped property of the image, causing it to draw incorrectly.

Try this around your image drawing line:

BOOL wasFlipped = [image isFlipped];
[image setFlipped:[self isFlipped]];
[image drawInRect:drawingRect
             fromRect:imageRect
            operation:NSCompositeSourceOver
             fraction:1];
[image setFlipped:wasFlipped];

See if that helps. If it does, look elsewhere in your code for something changing the image's flipped property and not putting it back.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文