首页 文章

从缩放视图拖动时NSView图像损坏

提问于
浏览
2

我有一个NSView的自定义子类,它实现拖放操作,将视图中的图像复制到另一个应用程序 . 我班上的相关代码如下:

#pragma mark -
#pragma mark Dragging Support
- (NSImage *)imageWithSubviews
{
    NSSize imgSize = self.bounds.size;
    NSBitmapImageRep *bir = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[self frame]];
    [self cacheDisplayInRect:[self frame] toBitmapImageRep:bir];

    NSImage* image = [[NSImage alloc]initWithSize:imgSize];
    [image addRepresentation:bir];

    return image;
}

- (void)mouseDown:(NSEvent *)theEvent
{
    NSSize dragOffset = NSMakeSize(0.0, 0.0); // not used in the method below, but required.
    NSPasteboard *pboard;
    NSImage *image = [self imageWithSubviews];
    pboard = [NSPasteboard pasteboardWithName:NSDragPboard];
    [pboard declareTypes:[NSArray arrayWithObject:NSTIFFPboardType]
                   owner:self];

    [pboard setData:[image TIFFRepresentation]
            forType:NSTIFFPboardType];

    [self dragImage:image
                 at:self.bounds.origin
             offset:dragOffset
              event:theEvent
         pasteboard:pboard
             source:self
          slideBack:YES];

    return;
}

#pragma mark -
#pragma mark NSDraggingSource Protocol

- (NSDragOperation)draggingSession:(NSDraggingSession *)session sourceOperationMaskForDraggingContext:(NSDraggingContext)context
{
    return NSDragOperationCopy;
}

- (BOOL)ignoreModifierKeysForDraggingSession:(NSDraggingSession *)session
{
    return YES;
}

这可以按预期工作,直到我调整主窗口的大小 . 主窗口仅以相同的增量增加尺寸/宽度,以在此视图中保持适当的比例 . 调整窗口大小时,视图会在屏幕上正确显示其内容 .

当我调整窗口大小超过25%时出现问题 . 虽然它仍然按预期显示,但拖出它的图像(例如,进入Pages)已损坏 . 它似乎有一部分图像重复在其自身之上 .

这是正常情况:

normal appearance

以下是在调整主窗口大小后将其拖动到Pages时的样子(缩小尺寸以显示在这里 - 想象它的大小是第一张图像的2-3倍):
corrupt appearance

请注意,我用虚线矩形突出显示了损坏的区域 .

还有一些注意事项:我的界限设置如 NSMakeRect(-200,-200,400,400) ,因为它使对称绘图更容易一些 . 当窗口调整大小时,我重新计算边界以保持NSView中心的0,0 . NSView总是正方形 .

最后,Apple文档声明了 cacheDisplayInRect:toBitmapImageRep:bitmapImageRep 参数的以下内容

NSBitmapImageRep对象 . 对于像素格式兼容性,应该从bitmapImageRepForCachingDisplayInRect:获取bitmapImageRep .

我尝试过使用 bitmapImageRepForCachingDisplayInRect: ,但是我看到的只是图像右上象限中金字塔的左下象限 . 这让我觉得我需要为 bitmapImageRep 的捕获添加偏移量,但我一直无法确定如何做到这一点 .

这是我尝试时 imageWithSubviews 的代码:

- (NSImage *)imageWithSubviews
{
    NSSize imgSize = self.bounds.size;
    NSBitmapImageRep *bir = [self bitmapImageRepForCachingDisplayInRect:[self bounds]];
    [self cacheDisplayInRect:[self bounds] toBitmapImageRep:bir];

    NSImage* image = [[NSImage alloc]initWithSize:imgSize];
    [image addRepresentation:bir];

    return image;
}

这就是生成图像的方式:

only lower left quadrant shows in upper right

这是在右上角绘制的左下象限的视图 .

在放大窗口后从NSView拖动时导致损坏的原因是什么?如何解决这个问题和/或更改我上面列出的方法的实现以避免问题?


更多信息:

当我将 imageWithSubviews 方法更改为:

- (NSImage *)imageWithSubviews
{

    NSSize imgSize = self.bounds.size;
    NSBitmapImageRep *bir = [[NSBitmapImageRep alloc] initWithFocusedViewRect:[self frame]];
    [self cacheDisplayInRect:[self bounds] toBitmapImageRep:bir];

    NSImage* image = [[NSImage alloc]initWithSize:imgSize];
    [image addRepresentation:bir];

    return image;
}

我得到一个没有缩放的损坏的图像,其中图像的左下象限再次在右上象限的顶部绘制,如下所示:

quadrant overwritten

世界上我做错了什么?


Solution:

虽然它没有解决使用 NSBitmapImageRep 绘制的核心问题,但以下 -imageWithSubviews 可防止损坏并输出正确的图像:

- (NSImage *)imageWithSubviews
{
    NSData *pdfData = [self dataWithPDFInsideRect:[self bounds]];
    NSImage* image = [[NSImage alloc] initWithData:pdfData];

    return image;
}

1 回答

  • 1

    根据上面的一些调试,我们确定问题出在 -imageWithSubviews .

    而不是使用 -cacheDisplayInRect:toBitmapImageRep: 为视图生成图像数据,而是将其更改为 -dataWithPDFInRect: 解决了问题 .

相关问题