4

多年来一直在努力解决问题。希望我能在这里得到答案。我用这个链接来平滑我的手绘图。在这段代码中,我能够设置线宽和颜色,但是当我尝试使用链接在其中包含撤消/重做功能时,我发现它非常困难,该链接在撤消重做时工作正常,但其徒手绘制并不流畅。

经过一些研究和编码后,我知道这是我认为防止撤消/重做的绘图的目的。

在第一个链接中有一个文件“CachedLIView.h/m”,当我使用它并尝试在其中包含撤消/重做时,我在以下方法中发现:

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2)
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p];

    [self drawBitmap]; // (3)
    [self setNeedsDisplay];

    [path removeAllPoints]; //(4)
}

此方法调用 drawBitMap: 方法,该方法实际上是在每次用户抬起手指并同时从“路径”中删除点时生成一个临时图像。

- (void)drawBitmap // (3)
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
    [[UIColor blackColor] setStroke];
    if (!incrementalImage) // first draw; paint background white by ...
    {
        UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
        [[UIColor greenColor] setFill];
        [rectpath fill]; // filling it with white
    }
    [incrementalImage drawAtPoint:CGPointZero];
    //[path stroke];
    for (UIBezierPath *_path in pathArray)
        [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

我将每条路径保存在一个数组中,以便我可以撤消/重做。(从第二个链接中获得了这个想法)。

以下是我修改为包含撤消/重做的该文件的完整代码:

    #import "CachedLIView.h"

@implementation CachedLIView
{
    UIBezierPath *path;
    UIImage *incrementalImage; // (1)
}

- (id)initWithFrame:(CGRect)frame // (1)
{
    if (self = [super initWithFrame:frame])
    {
        [self setMultipleTouchEnabled:NO]; // (2)
        //        [self setBackgroundColor:[UIColor whiteColor]];
//                path = [[UIBezierPath alloc] init];
//                [path setLineWidth:3];

        pathArray=[[NSMutableArray alloc]init];
        bufferArray=[[NSMutableArray alloc]init];
        [self drawBitmap];
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    NSLog(@"in drawrect pathArray[count]: %d", pathArray.count);

    [incrementalImage drawInRect:rect]; // (3)

    //[[UIColor blackColor] setStroke];
    //[path stroke];
    for (UIBezierPath *_path in pathArray)
        [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}


- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    path = [[UIBezierPath alloc] init];
    path.lineWidth = 3;

    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path moveToPoint:p];

    [pathArray addObject:path];

}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p];


    [self setNeedsDisplay];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2)
{
    UITouch *touch = [touches anyObject];
    CGPoint p = [touch locationInView:self];
    [path addLineToPoint:p];

    [self drawBitmap]; // (3)
    [self setNeedsDisplay];

    [path removeAllPoints]; //(4)
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self touchesEnded:touches withEvent:event];
}

- (void)drawBitmap // (3)
{
    UIGraphicsBeginImageContextWithOptions(self.bounds.size, YES, 0.0);
    [[UIColor blackColor] setStroke];
    if (!incrementalImage) // first draw; paint background white by ...
    {
        UIBezierPath *rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; // enclosing bitmap by a rectangle defined by another UIBezierPath object
        [[UIColor greenColor] setFill];
        [rectpath fill]; // filling it with white
    }
    [incrementalImage drawAtPoint:CGPointZero];
    //[path stroke];
    for (UIBezierPath *_path in pathArray)
        [_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
    incrementalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
}

#pragma mark - undo/redo
-(void)undoButtonClicked
{
    if([pathArray count]>0){
        UIBezierPath *_path=[pathArray lastObject];
        [bufferArray addObject:_path];
        [pathArray removeLastObject];

        [self drawBitmap];
        [self setNeedsDisplay];
    }
}

-(void)redoButtonClicked
{
    if([bufferArray count]>0){
        UIBezierPath *_path=[bufferArray lastObject];
        [pathArray addObject:_path];
        [bufferArray removeLastObject];

        [self drawBitmap];
        [self setNeedsDisplay];
    }
}
@end

.h 文件是:

#import <UIKit/UIKit.h>

@interface CachedLIView : UIView
{
    NSMutableArray *pathArray;
    NSMutableArray *bufferArray;
    UIBezierPath *myPath;

}
-(void)undoButtonClicked;
-(void)redoButtonClicked;
@end

请帮我。我做错了什么。pathArray 计数工作正常。但无法在屏幕上显示撤消/重做效果。

4

2 回答 2

2

嘿,我无法获得您的全部代码,但我可以建议您如何实现这些东西,

对于手绘图像中的重做和撤消,您可以capture image render在触摸开始或触摸结束时进行manage stack of that renders。然后根据您的要求(重做/撤消)使用缓存中的渲染。所以步骤就像,

1) 触摸板时捕获渲染并保存。并在缓存中管理该序列。

  • 因此,对于每次触摸开始,您都必须按顺序捕获图像并保存。

2)当您当时按撤消键时,获取最后一次渲染并将其替换为您的电路板。

3) 对于重做,您可以检查是否有比当前替换的渲染更高的渲染可用。意味着您可以通过最后更新的渲染启用和禁用该按钮。

4)完成保存图像后不要忘记清空缓存,以便您可以管理堆栈以进行下一次绘图。


  • 如果你不明白这个想法,请告诉我。
于 2012-12-06T13:46:42.373 回答
1

最后我得到了它,并且也能够使用撤消/重做功能进行平滑的绘制。这是导致问题的drawBitMap方法..

我在任何地方都删除(注释)了对这个 [self drawBitmap] 方法的调用。

我在 touchesEnded 和 undo/redo 方法中调用了这个方法。我觉得没有必要使用这种方法,因为每当用户从屏幕上抬起手指时,它都会进行缓存(以加快绘图速度),创建一个新图像并将其放置在屏幕上,然后删除旧图像,并且用户有一种错觉,他是连续画。但是只有在你真的想提高性能的极端情况下才需要这种缓存(如果你的内存不足并且你的绘图开始变得丑陋)。

所以我决定在以后的某个阶段保存这个缓存机制并删除它。尽管我无法找出为什么我的撤消/重做功能无法使用它,但我认为当我缓存了新图像并将其放置在屏幕上时(当用户抬起手指时),它就会产生问题,因为我必须保留最后缓存的图像(用于撤消/重做)。

我将在稍后阶段使用缓存,并尝试优化我的代码。

还要记得删除 [myPath removeAllPoints]; touchesEnded: method 中的这一行,否则一旦您抬起手指,您的绘图就会消失。

希望这会对某人有所帮助。这是 touchesEnded: 修改方法。

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event // (2)
{
       UITouch *touch = [touches anyObject];
CGPoint p = [touch locationInView:self];
[path addLineToPoint:p];

    //[self drawBitmap]; // CAUSES PROBLEM IF UNCOMMENTED AND UNDO/REDO WILL STOP WORKING..
    [self setNeedsDisplay];


    //[myPath removeAllPoints];// LINE GETS DRAWN BUT VANISHED WHEN TOUCH LIFTED OFF FROM SCREEN..
    ctr = 0;
}

后来我将此功能添加到 SmoothedBIView 并且它工作得很好。

于 2012-12-11T11:52:17.047 回答