2012-12-07 77 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