Objective c 将视图层次绘制到Cocoa中的特定上下文中
对于应用程序的一部分,我需要创建某个视图及其所有子视图的图像 为此,我创建了一个上下文,它包装了一个与视图大小相同的位图,但我不确定如何在其中绘制视图层次结构。我可以只通过设置上下文并显式调用drawRect来绘制单个视图,但这并不处理所有子视图 我在NSView界面中看不到任何有助于此的内容,因此我怀疑解决方案可能位于更高的级别。您可以使用它将发送到的视图的整个层次结构呈现为PDF格式,并作为Objective c 将视图层次绘制到Cocoa中的特定上下文中,objective-c,cocoa,macos,Objective C,Cocoa,Macos,对于应用程序的一部分,我需要创建某个视图及其所有子视图的图像 为此,我创建了一个上下文,它包装了一个与视图大小相同的位图,但我不确定如何在其中绘制视图层次结构。我可以只通过设置上下文并显式调用drawRect来绘制单个视图,但这并不处理所有子视图 我在NSView界面中看不到任何有助于此的内容,因此我怀疑解决方案可能位于更高的级别。您可以使用它将发送到的视图的整个层次结构呈现为PDF格式,并作为NSData对象返回。然后,您可以使用它执行任何操作,包括将其渲染为位图 但您确定要位图表示吗?毕竟,
NSData
对象返回。然后,您可以使用它执行任何操作,包括将其渲染为位图
但您确定要位图表示吗?毕竟,PDF可以(至少在理论上)独立于分辨率。是的,对于这种特定用途,未缩放的图像数据正是我所需要的。在锁定视图焦点后,可以使用该视图渲染自身(及其子视图)进入给定的矩形。我发现自己编写绘图代码是最好的方法:
- 处理潜在的透明度问题(其他一些选项会为整个图像添加白色背景)
- 演出好多了
ImageWithSubview的实现中添加[self-drawRect:[self-bounds]]]
- (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;
}
您想要做的事情已经明确可用了。请参阅10.4 AppKit发行说明中的“NSView图形重定向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:]
10.4中“NSView图形重定向API”的链接如果视图位于NSScrollView中,则会产生副作用,即显示视图的内容被裁剪为在滚动视图中可见的内容,并包括任何滚动条。