Mar*_* A. 6 objective-c uiview cgcontext quartz-2d
我有一个绘图应用程序,我想在其中创建一个撤消方法.绘图发生在TouchesMoved:方法中.
我正在尝试创建一个CGContextRef并将其推送到堆栈或将其保存在一个上下文属性中,以后可以恢复,但没有任何运气.任何建议都会很棒.这是我的......
UIImageView *drawingSurface;
CGContextRef undoContext;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[drawingSurface.image drawInRect:CGRectMake(0, 0, drawingSurface.image.size.width, drawingSurface.image.size.height)];
UIGraphicsPushContext(context);
// also tried but cant figure how to restore it
undoContext = context;
UIGraphicsEndImageContext();
}
Run Code Online (Sandbox Code Playgroud)
然后我有一个由我的撤销按钮触发的方法......
- (IBAction)restoreUndoImage {
UIGraphicsBeginImageContext(self.view.frame.size);
UIGraphicsPopContext();
drawingSurface.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我相信我的drawingSurface被指定为nil,因为它只是删除了图像中的所有内容.
我的猜测是我不能用pop这样推.但我似乎无法弄清楚如何只保存上下文然后将其推回到drawingSurface上.Hmmmm.任何帮助都会......嗯......乐于助人.提前致谢 -
并且,仅供参考,这是我正在做的绘制到屏幕,这是很好的工作.这是在我的TouchesMoved中:
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[drawingSurface.image drawInRect:CGRectMake(0, 0, drawingSurface.image.size.width, drawingSurface.image.size.height)];
CGContextSetLineCap(context, kCGLineCapRound); //kCGLineCapSquare, kCGLineCapButt, kCGLineCapRound
CGContextSetLineWidth(context, self.brush.size); // for size
CGContextSetStrokeColorWithColor (context,[currentColor CGColor]);
CGContextBeginPath(context);
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
CGContextStrokePath(context);
drawingSurface.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Run Code Online (Sandbox Code Playgroud)
我认为您处理问题的方式是错误的并且上下文令人困惑。
在即时模式 API 中,您可以通过推送/弹出保存对象的“状态”,而不是图形表示。状态由线宽、颜色和位置等内容组成。图形表示是绘制操作的结果(位图),并且通常是您不想保存的内容。
相反,请尝试保存用于创建绘图的“信息”。
我最初的建议是将形状创建和绘画分离。在 OSX 上,您可以使用 NSBezierPath,但对于 iOS,我们必须使用点数组。
例如给定这个协议:
// ViewController.h
@protocol DrawSourceProtocol <NSObject>
- (NSArray*)pathsToDraw;
@end
@interface ViewController : UIViewController<DrawSourceProtocol>
@end
Run Code Online (Sandbox Code Playgroud)
您可以实现这些功能:
// ViewController.m
@interface ViewController () {
NSMutableArray *currentPath;
NSMutableArray *allPaths;
MyView *view_;
}
@end
...
- (void)viewDidLoad {
[super viewDidLoad];
currentPath = [[NSMutableArray alloc] init];
allPaths = [[NSMutableArray alloc] init];
view_ = (MyView*)self.view;
view_.delegate = self;
}
- (NSArray*)pathsToDraw {
// Return the currently draw path too
if (currentPath && currentPath.count) {
NSMutableArray *allPathsPlusCurrent = [[NSMutableArray alloc] initWithArray:allPaths];
[allPathsPlusCurrent addObject:currentPath];
return allPathsPlusCurrent;
}
return allPaths;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
currentPath = [[NSMutableArray alloc] init];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// When a touch ends, save the current path
[allPaths addObject:currentPath];
currentPath = [[NSMutableArray alloc] init];
[view_ setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
// We store the point with the help of NSValue
[currentPath addObject:[NSValue valueWithCGPoint:currentPoint]];
// Update the view
[view_ setNeedsDisplay];
}
Run Code Online (Sandbox Code Playgroud)
现在对您的视图进行子类化(我在这里将我的视图称为 MyView)并实现如下所示的内容:
// MyView.h
#import "ViewController.h"
@protocol DrawSourceProtocol;
@interface MyView : UIView {
__weak id<DrawSourceProtocol> delegate_;
}
@property (weak) id<DrawSourceProtocol> delegate;
@end
// MyView.m
@synthesize delegate = delegate_;
...
- (void)drawRect:(CGRect)rect {
NSLog(@"Drawing!");
// Setup a context
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 2.0);
// Get the paths
NSArray *paths = [delegate_ pathsToDraw];
for (NSArray *aPath in paths) {
BOOL firstPoint = TRUE;
for (NSValue *pointValue in aPath) {
CGPoint point = [pointValue CGPointValue];
// Always move to the first point
if (firstPoint) {
CGContextMoveToPoint(context, point.x, point.y);
firstPoint = FALSE;
continue;
}
// Draw a point
CGContextAddLineToPoint(context, point.x, point.y);
}
}
// Stroke!
CGContextStrokePath(context);
}
Run Code Online (Sandbox Code Playgroud)
这里唯一需要注意的是 setNeedsDisplay 的性能不是很好。最好使用 setNeedsDisplayInRect:,请参阅我的上一篇文章,了解确定“绘制” rect 的有效方法。
至于撤消?您的撤消操作只是从 allPaths 数组中弹出最后一个对象。这个练习我将留给你:)
希望这可以帮助!
| 归档时间: |
|
| 查看次数: |
3111 次 |
| 最近记录: |