4

アプリケーションの一部で、特定のビューとそのすべてのサブビューのイメージを作成する必要があります。

これを行うには、ビューと同じサイズのビットマップをラップするコンテキストを作成していますが、ビュー階層をそれに描画する方法がわかりません。コンテキストを設定して drawRect を明示的に呼び出すだけで単一のビューを描画できますが、これはすべてのサブビューを処理するわけではありません。

NSView インターフェイスにはこれに役立つものは何も表示されないため、解決策はより高いレベルにあると思われます。

4

4 に答える 4

2

を使用して、送信先のビューの階層全体をPDFにレンダリングし、オブジェクト-[NSView dataWithPDFInsideRect:]として返すことができます。NSDataその後、ビットマップにレンダリングするなど、それを使って好きなことを行うことができます。

しかし、ビットマップ表現が必要ですか?結局のところ、そのPDFは(少なくとも理論的には)解像度に依存しない可能性があります。

于 2008-08-18T17:19:03.273 に答える
2

自分で描画コードを書くことが、次のことを行う最善の方法であることがわかりました。

  • 潜在的な透過性の問題に対処する (他のオプションのいくつかは、画像全体に白い背景を追加します)
  • パフォーマンスははるかに優れていました

以下のコードは、境界からフレームへのスケーリングの問題に対処していないため、完全ではありませんが、isFlipped 状態を考慮しており、私が使用した目的に対しては非常にうまく機能します。サブビュー(およびサブサブビュー...再帰的に)のみを描画することに注意してください。ただし、それ自体も描画するのは非常に簡単です..[self drawRect:[self bounds]]の実装に a を追加するだけです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;
}
于 2008-09-15T20:21:51.760 に答える
1

ビューにフォーカスをロックした後に使用-[NSBitmapImageRep initWithFocusedViewRect:]して、ビュー自体(およびそのサブビュー)を指定された長方形にレンダリングすることができます。

于 2008-08-19T01:25:23.587 に答える
1

あなたがやりたいことは、すでに明示的に利用可能です。10.4 AppKit リリース ノートの「NSView Drawing Redirection API」セクションを参照してください。

キャッシュ用の 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:]
于 2008-09-16T12:26:15.907 に答える