2012-12-07 30 views
2

我有一个NSView的自定义子类,实现拖放操作以将视图中的图像复制到另一个应用程序。我的班级中的相关代码如下所示:从缩放视图拖动时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%时,问题就出现了。虽然它仍然按预期显示,但拖拽它的图像(例如页面)已损坏。它看起来有一部分图像重复在其本身之上。

下面是它看起来像正常:

normal appearance

这里是个什么样子,当拖动到页面调整主窗口后,使之大(缩小显示在这里像 - 想象在2-3倍大小的第一个图像): corrupt appearance

请注意,我用虚线矩形突出显示腐败区域。

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

最后,苹果的文档说明其bitmapImageRep参数以下在cacheDisplayInRect:toBitmapImageRep:应该

的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

我在做什么错了?


解决方案:

虽然它没有解决与NSBitmapImageRep绘制的核心问题,下面-imageWithSubviews防止腐败并输出正确的图像:

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

    return image; 
} 
+0

你不使用NSImageView的任何原因? – paulmelnikow

+0

您是否检查过是否多次调用“-imageWithSubviews”? – paulmelnikow

+0

我检查过了,'-imageWithSubviews'只被调用一次。金字塔是根据用户输入(未导入的照片)动态绘制的。我从来没有考虑过使用'NSImageView',我不知道为什么这将是一个更好的选择。对我来说这很奇怪,只有当我将窗口大小放大到超过某个阈值时才会发生,然后才会在金字塔上拖动。它在窗口/视图本身中显得很好。 – Clay

回答

1

基于一些在上面的调试中,我们确定问题出在-imageWithSubviews

代替使用-cacheDisplayInRect:toBitmapImageRep:生成视图的图像数据,将其更改为可解决此问题。

+0

我会将我修改的'-imageWithSubviews'添加到问题的底部。再次感谢! – Clay