8

ウィンドウ全体を占める NSImageView があります。画像ビューに境界線はなく、左下に表示するように設定されています。したがって、これは、ウィンドウのサイズがどのように変更されても、ビューの原点が実際の画像の原点と一致することを意味します。

また、この画像は、画面にフル スケールで収まるサイズよりもはるかに大きくなっています。そのため、画像のサイズを比例的に縮小するように imageview を設定しています。ただし、この倍率はどこにも見つからないようです。

私の最終的な目標は、マウス ダウン イベントを実際の画像座標にマッピングすることです。これを行うには、もう 1 つ情報が必要だと思います...表示された NSImage が実際にどれだけ大きいか。

を見ると[imageView bounds]、画像ビューの境界矩形が得られます。これは通常、画像よりも大きくなります。

4

4 に答える 4

4

これで必要なものが得られると思います:

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    
}
于 2012-08-06T21:17:23.300 に答える
3

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
于 2015-01-19T20:09:40.183 に答える
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;
}
于 2012-08-07T03:23:58.693 に答える