Drawing a hierarchy of views in a specific context in Cocoa

For part of my application, I need to create an image of a certain type and all its subzones.

To do this, I create a context that wraps a bitmap with the same size as the view, but I'm not sure how to draw the hierarchy of the views. I can draw one view simply by setting the context and explicitly calling drawRect, but this does not apply to all subzones.

I do not see anything in the NSView interface that can help with this, so I suspect that the solution may lie at a higher level.

+3
source share
5 answers

I found that writing the drawing code myself was the best way:

  • ( ).

, , isFlipped , . , subviews ( sububviews,... ), , [self drawRect:[self bounds]] imageWithSubviews.

- (void)drawSubviews
{
    BOOL flipped = [self isFlipped];

    for ( NSView *subview in [self subviews] ) {

        // changes the coordinate system so that the local coordinates of the subview (bounds) become the coordinates of the superview (frame)
        // the transform assumes bounds and frame have the same size, and bounds origin is (0,0)
        // handling of 'isFlipped' also probably unreliable
        NSAffineTransform *transform = [NSAffineTransform transform];
        if ( flipped ) {
            [transform translateXBy:subview.frame.origin.x yBy:NSMaxY(subview.frame)];
            [transform scaleXBy:+1.0 yBy:-1.0];
        } else
            [transform translateXBy:subview.frame.origin.x yBy:subview.frame.origin.y];
        [transform concat];

        // recursively draw the subview and sub-subviews
        [subview drawRect:[subview bounds]];
        [subview drawSubviews];

        // reset the transform to get back a clean graphic contexts for the rest of the drawing
        [transform invert];
        [transform concat];
    }
}

- (NSImage *)imageWithSubviews
{
    NSImage *image = [[[NSImage alloc] initWithSize:[self bounds].size] autorelease];
    [image lockFocus];
    // it seems NSImage cannot use flipped coordinates the way NSView does (the method 'setFlipped:' does not seem to help)
    // Use instead an NSAffineTransform
    if ( [self isFlipped] ) {
        NSAffineTransform *transform = [NSAffineTransform transform];
        [transform translateXBy:0 yBy:NSMaxY(self.bounds)];
        [transform scaleXBy:+1.0 yBy:-1.0];
        [transform concat];
    }
    [self drawSubviews];
    [image unlockFocus];
    return image;
}
+2

-[NSView dataWithPDFInsideRect:], PDF, NSData. , , .

, ? , PDF ( ) .

+2

, , . . "API NSView" 10.4 AppKit.

NSBitmapImageRep :

NSGraphicsContext *bitmapGraphicsContext = [NSGraphicsContext graphicsContextWithBitmapImageRep:cacheBitmapImageRep];
[NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:bitmapGraphicsContext];
[[NSColor clearColor] set];
NSRectFill(NSMakeRect(0, 0, [cacheBitmapImageRep size].width, [cacheBitmapImageRep size].height));
[NSGraphicsContext restoreGraphicsState];

:

-[NSView cacheDisplayInRect:toBitmapImageRep:]

,

-[NSView displayRectIgnoringOpacity:inContext:]
+1

, - , .

0

Source: https://habr.com/ru/post/1696435/


All Articles