2012-07-29 65 views
7

我有一個NSImageView,佔用了一個窗口的全部範圍。圖像視圖沒有邊框,其設置顯示在左下角。所以這意味着無論窗口如何調整大小,視圖的來源都與實際圖像的原點相匹配。在NSImageView中獲取NSImage的界限

此外,圖像比我可以合理地適合在屏幕上的全尺寸大得多。所以我也有圖像視圖按比例縮小圖像的大小。但是,我似乎無法在任何地方找到這個比例因子。

我的最終目標是將鼠標向下的事件映射到實際的圖像座標。要做到這一點,我想我需要更多的信息.​​.....顯示的NSImage實際上有多大。

如果我看一下[imageView bounds],我會得到圖像視圖的邊界矩形,該矩形一般會比圖像大。

+0

我試過了。框架和邊界等都是相對於NSView/NSWindow類型的對象。所以我可以得到視圖或窗口本身的邊界框架......問題是NSImageView並沒有繪製它的所有邊界。部分視圖是空白的。我需要的是NSImageView縮小其圖像的量,或者ImageView實際繪製的邊界矩形(與其擁有的相反) – wrjohns 2012-07-29 19:42:19

+0

現在,我將採用一種解決方法,其中我不允許窗口被調整大小,並從窗口中刪除所有其他UI元素(如標題欄),以便我知道超級視圖邊界= NSImageView邊界=實際圖像的大小。 – wrjohns 2012-07-29 19:44:09

+0

NSImages沒有框架。他們**有**尺寸,但尺寸是全尺寸圖像,而不是實際尺寸。 – wrjohns 2012-07-29 23:09:05

回答

2

我認爲這給了你所需要的:

NSRect imageRect = [imageView.cell drawingRectForBounds: imageView.bounds]; 

它返回視圖中的圖像的原點的偏移量,它的大小。

而對於你最終重新映射鼠標座標,這樣的事情在您的自定義視圖類應該努力的目標......

- (void)mouseUp:(NSEvent *)event 
{ 
    NSPoint eventLocation = [event locationInWindow];  
    NSPoint location = [self convertPoint: eventLocation fromView: nil]; 

    NSRect drawingRect = [self.cell drawingRectForBounds:self.bounds]; 

    location.x -= drawingRect.origin.x; 
    location.y -= drawingRect.origin.y; 

    NSSize frameSize = drawingRect.size; 
    float frameAspect = frameSize.width/frameSize.height; 

    NSSize imageSize = self.image.size; 
    float imageAspect = imageSize.width/imageSize.height; 

    float scaleFactor = 1.0f; 

    if(imageAspect > frameAspect) { 

     ///in this case image.width == frame.width 
     scaleFactor = imageSize.width/frameSize.width; 

     float imageHeightinFrame = imageSize.height/scaleFactor; 

     float imageOffsetInFrame = (frameSize.height - imageHeightinFrame)/2; 

     location.y -= imageOffsetInFrame; 

    } else { 
     ///in this case image.height == frame.height 
     scaleFactor = imageSize.height/frameSize.height; 

     float imageWidthinFrame = imageSize.width/scaleFactor; 

     float imageOffsetInFrame = (frameSize.width - imageWidthinFrame)/2; 

     location.x -= imageOffsetInFrame; 
    } 

    location.x *= scaleFactor; 
    location.y *= scaleFactor; 

    //do something with you newly calculated mouse location  
} 
+0

對不起...第一行結束了不起作用。我NSLog'ed計算矩形,並調整窗口的大小,使縱橫比發生變化(但圖像單元設置爲按比例繪製),圖像單元的邊界匹配窗口的邊界,而不是顯示的圖像。我開始認爲沒有API調用。我能做的是計算原始非縮放圖像的縱橫比...並用它來計算調整大小的窗口中的圖像範圍 – wrjohns 2012-08-06 23:10:37

+0

鑑於描述瞭如何設置可能正確的事情。上面的代碼的其餘部分然後計算圖像本身的偏移量。你試過了其餘的代碼嗎?除了我的視圖和窗口邊界不匹配,因爲我有一個邊界,我正在做一個非常類似的事情。您可能不需要最終的* = scaleFactor,因爲我需要圖像空間中的座標(即......相對於圖像的實際大小)。 – combinatorial 2012-08-07 02:30:48

+0

我確實嘗試了其餘的代碼。但隨着drawingRect被關閉,最終的計算座標也被關閉。我決定採用兩種方法來實現我想要的功能:從NSWindowDelegate實現一些方法,並強制任何手動調整大小以保留寬高比,然後在我的mouseUp:方法中,我可以假設圖像大小=窗口大小 – wrjohns 2012-08-07 03:14:40

0

正如我在上述結構評論所指出的,這裏是我採取的方法:

// the view that mouseUp: is part of doesnt draw anything. I'm layering it 
// in the window hierarchy to intercept mouse events. I suppose I could have 
// subclassed NSImageView instead, but I went this route. isDragging is 
// an ivar...its cleared in mouseDown: and set in mouseDragged: 
// this view has no idea what the original unscaled image size is, so 
// rescaling is done by caller 
- (void)mouseUp:(NSEvent *)theEvent 
{ 

    if (!isDragging) 
    { 
     NSPoint rawPoint = [theEvent locationInWindow]; 
     NSImageView *view = self.subviews.lastObject; 

     point = [self convertPoint:rawPoint fromView:view]; 
     point.x /= view.bounds.size.width; 
     point.y /= view.bounds.size.height; 

     [owner mouseClick:point]; 

    } 
} 

而且在我NSWindowController,這是我的鼠標視圖窗口委託,我有:

static int resizeMode=-1; 

- (void)windowDidEndLiveResize:(NSNotification *)notification 
{ 
    if ([notification object]==frameWindow) 
     self.resizeFrameSelection=0; 
    resizeMode = -1; 
} 

- (NSSize)windowWillResize:(NSWindow *)sender toSize:(NSSize)frameSize 
{ 

    if (sender==frameWindow) 
    { 
     float imageAspectRatio = (float)movie.movieSize.width/(float)movie.movieSize.height; 
     float newH = frameSize.height; 
     float newW = frameSize.width; 
     float currH = sender.frame.size.height; 
     float currW = sender.frame.size.width; 
     float deltaH = abs(newH-currH); 
     float deltaW = abs(newW-currW); 

     // lock onto one dimension to key off of, per drag. 
     if (resizeMode==1 || (resizeMode==-1 && deltaW<deltaH)) 
     { 
      // adjust width to match aspect ratio 
      frameSize.width = frameSize.height * imageAspectRatio; 
      resizeMode=1; 
     } 
     else 
     { 
      // adjust height to match aspect ratio 
      frameSize.height = frameSize.width/imageAspectRatio; 
      resizeMode=2; 
     } 
    } 

    return frameSize; 
} 
0

因爲我還沒有找到任何解決方案來獲取NSImageView中的真實圖像幀,所以我手動進行了圖像計算,考慮了它的所有屬性(縮放,對齊和邊框)。這可能不是最有效的代碼,可能會有0.5-1像素與真實圖像有微小的偏差,但它接近原始圖像(我知道這個問題很老,但解決方案可能會幫助其他人):

@implementation NSImageView (ImageFrame) 

// ------------------------------------------------------------------------- 
// -imageFrame 
// ------------------------------------------------------------------------- 
- (NSRect)imageFrame 
{ 
    // Find the content frame of the image without any borders first 
    NSRect contentFrame = self.bounds; 
    NSSize imageSize = self.image.size; 
    NSImageFrameStyle imageFrameStyle = self.imageFrameStyle; 

    if (imageFrameStyle == NSImageFrameButton || 
     imageFrameStyle == NSImageFrameGroove) 
    { 
     contentFrame = NSInsetRect(self.bounds, 2, 2); 
    } 

    else if (imageFrameStyle == NSImageFramePhoto) 
    { 
     contentFrame = NSMakeRect(contentFrame.origin.x + 1, 
            contentFrame.origin.y + 2, 
            contentFrame.size.width - 3, 
            contentFrame.size.height - 3); 
    } 

    else if (imageFrameStyle == NSImageFrameGrayBezel) 
    { 
     contentFrame = NSInsetRect(self.bounds, 8, 8); 
    } 


    // Now find the right image size for the current imageScaling 
    NSImageScaling imageScaling = self.imageScaling; 
    NSSize drawingSize = imageSize; 

    // Proportionally scaling 
    if (imageScaling == NSImageScaleProportionallyDown || 
     imageScaling == NSImageScaleProportionallyUpOrDown) 
    { 
     NSSize targetScaleSize = contentFrame.size; 
     if (imageScaling == NSImageScaleProportionallyDown) 
     { 
      if (targetScaleSize.width > imageSize.width) targetScaleSize.width = imageSize.width; 
      if (targetScaleSize.height > imageSize.height) targetScaleSize.height = imageSize.height; 
     } 

     NSSize scaledSize = [self sizeByScalingProportionallyToSize:targetScaleSize fromSize:imageSize]; 
     drawingSize = NSMakeSize(scaledSize.width, scaledSize.height); 
    } 

    // Axes independent scaling 
    else if (imageScaling == NSImageScaleAxesIndependently) 
     drawingSize = contentFrame.size; 


    // Now get the image position inside the content frame (center is default) from the current imageAlignment 
    NSImageAlignment imageAlignment = self.imageAlignment; 
    NSPoint drawingPosition = NSMakePoint(contentFrame.origin.x + contentFrame.size.width/2.0 - drawingSize.width/2.0, 
              contentFrame.origin.y + contentFrame.size.height/2.0 - drawingSize.height/2.0); 

    // NSImageAlignTop/NSImageAlignTopLeft/NSImageAlignTopRight 
    if (imageAlignment == NSImageAlignTop || 
     imageAlignment == NSImageAlignTopLeft || 
     imageAlignment == NSImageAlignTopRight) 
    { 
     drawingPosition.y = contentFrame.origin.y+contentFrame.size.height - drawingSize.height; 

     if (imageAlignment == NSImageAlignTopLeft) 
      drawingPosition.x = contentFrame.origin.x; 
     else if (imageAlignment == NSImageAlignTopRight) 
      drawingPosition.x = contentFrame.origin.x + contentFrame.size.width - drawingSize.width; 
    } 

    // NSImageAlignBottom/NSImageAlignBottomLeft/NSImageAlignBottomRight 
    else if (imageAlignment == NSImageAlignBottom || 
      imageAlignment == NSImageAlignBottomLeft || 
      imageAlignment == NSImageAlignBottomRight) 
    { 
     drawingPosition.y = contentFrame.origin.y; 

     if (imageAlignment == NSImageAlignBottomLeft) 
      drawingPosition.x = contentFrame.origin.x; 
     else if (imageAlignment == NSImageAlignBottomRight) 
      drawingPosition.x = contentFrame.origin.x + contentFrame.size.width - drawingSize.width; 
    } 

    // NSImageAlignLeft/NSImageAlignRight 
    else if (imageAlignment == NSImageAlignLeft) 
     drawingPosition.x = contentFrame.origin.x; 

    // NSImageAlignRight 
    else if (imageAlignment == NSImageAlignRight) 
     drawingPosition.x = contentFrame.origin.x + contentFrame.size.width - drawingSize.width; 


    return NSMakeRect(round(drawingPosition.x), 
         round(drawingPosition.y), 
         ceil(drawingSize.width), 
         ceil(drawingSize.height)); 
} 

// ------------------------------------------------------------------------- 
// -sizeByScalingProportionallyToSize:fromSize: 
// ------------------------------------------------------------------------- 
- (NSSize)sizeByScalingProportionallyToSize:(NSSize)newSize fromSize:(NSSize)oldSize 
{ 
    CGFloat widthHeightDivision = oldSize.width/oldSize.height; 
    CGFloat heightWidthDivision = oldSize.height/oldSize.width; 

    NSSize scaledSize = NSZeroSize; 
    if (oldSize.width > oldSize.height) 
    { 
     if ((widthHeightDivision * newSize.height) >= newSize.width) 
     { 
      scaledSize = NSMakeSize(newSize.width, heightWidthDivision * newSize.width); 
     } else { 
      scaledSize = NSMakeSize(widthHeightDivision * newSize.height, newSize.height); 
     } 

    } else { 

     if ((heightWidthDivision * newSize.width) >= newSize.height) 
     { 
      scaledSize = NSMakeSize(widthHeightDivision * newSize.height, newSize.height); 
     } else { 
      scaledSize = NSMakeSize(newSize.width, heightWidthDivision * newSize.width); 
     } 
    } 

    return scaledSize; 
} 

@end