无法通过平滑的自由手绘进行撤消/重做 [英] Not able to include undo/redo with smooth free hand drawing

查看:86
本文介绍了无法通过平滑的自由手绘进行撤消/重做的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

许多天以来一直在努力解决问题。希望我能在这里得到答案。我使用了链接来平滑我的自由手绘图。在此代码中,我能够设置线宽和颜色,但是当我尝试使用链接在撤消重做时效果很好,但其徒手操作并不顺利。



经过一些研究和编码后,我知道它的绘画方式是防止撤消/重做。



在第一个链接中,当我使用此文件并尝试在其中包含撤消/重做操作时,存在一个文件 CachedLIView.h / m,我发现以下内容方法:

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

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

[路径removeAllPoints]; //(4)
}

此方法正在调用drawBitMap:该方法实际上是在生成

 -(void)drawBitmap //( 3)
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size,YES,0.0);
[[UIColor blackColor] setStroke];
if(!incrementalImage)//首先绘制; $ ...
{
UIBezierPath * rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; //用另一个UIBezierPath对象
[[UIColor greenColor] setFill]定义的矩形包围位图。
[rectpath fill]; //用白色
填充}
[incrementalImage drawAtPoint:CGPointZero];
// [路径笔触];
用于(UIBezierPath * pathPath中的_path)
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
递增图像= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}

我正在保存数组中的每个路径,以便可以撤消/重做。 (将此想法从第二个链接中提取出来)。



以下是该文件的完整代码,我已对其进行修改以包括撤消/重做:

  #import CachedLIView.h 

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

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

pathArray = [[NSMutableArray alloc] init];
bufferArray = [[NSMutableArray alloc] init];
[self drawBitmap];
}
返回自我;
}

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

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

// [[UIColor blackColor] setStroke];
// [路径笔触];
用于(UIBezierPath * pathPath中的_path)
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
}


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

UITouch * touch = [触摸anyObject];
CGPoint p = [触摸locationInView:self];
[路径moveToPoint:p];

[pathArray addObject:path];

}

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


[self setNeedsDisplay];
}

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

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

[路径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)//首先绘制; $ ...
{
UIBezierPath * rectpath = [UIBezierPath bezierPathWithRect:self.bounds]; //用另一个UIBezierPath对象
[[UIColor greenColor] setFill]定义的矩形包围位图。
[rectpath fill]; //用白色
填充}
[incrementalImage drawAtPoint:CGPointZero];
// [路径笔触];
用于(UIBezierPath * pathPath中的_path)
[_path strokeWithBlendMode:kCGBlendModeNormal alpha:1.0];
递增图像= UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}

#pragma mark-撤消/重做
-(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计数工作正常。但不能在屏幕上显示撤消/重做效果。

解决方案

最后,我明白了这一点,并且能够使用撤消/重做平滑绘制功能。
是导致问题的 drawBitMap 方法。



我删除(注释)对此[self drawBitmap]的调用方法无处不在。



我在touchesEnded和撤消/重做方法中调用了此方法。我觉得不需要使用此方法,因为每当用户从屏幕上抬起手指时,都会进行缓存(以加快绘制速度),因此会创建一个新图像并将其放置在屏幕上,删除旧图像并且用户有一种幻觉,即连续绘图。但是,只有在您确实想提高性能的情况下(如果内存不足并且绘图开始变得难看),才需要在极端情况下使用此缓存。



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



我将在以后使用缓存,并尝试优化代码。



还记得删除[myPath removeAllPoints];这条线来自touchesEnded:方法,否则,一旦您抬起手指,您的图形就会消失。



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

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

// [self drawBitmap]; //如果未注释且撤消/重做将停止工作,则会导致问题。.
[self setNeedsDisplay];


// [myPath removeAllPoints]; //当从屏幕上移开时,画线的线条消失了。.
ctr = 0;
}

后来,我将此功能添加到SmoothedBIView中,并且工作得很好。 p>

Struggling with issue since many days. Hope i can get an answer here. i have used this link to smoothen my free hand drawing. In this code i was able to set line width and color but i am finding it much difficult when i try to include undo/redo feauture in it using this link which is working fine on undo redo but its free hand dreawing is not smooth.

After some research and coding i am to know that its the cathing of drawing which is i think preventing the undo/redo.

In the first link there is a file "CachedLIView.h/m" when i used this and try to include undo/redo in this, i found that in the following method:

- (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)
}

this method is calling drawBitMap: method which is actually generating a temporary image every time user lifts his finger and simultaneously removing points from 'path'.

- (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();
}

i am saving every path in an array so that i can do undo/redo. (took this idea from second link).

below is the complete code of this file that i have modified to include undo/redo:

    #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 file is:

#import <UIKit/UIKit.h>

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

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

Please help me. What i am doing wrong. pathArray count is working correct. but not able to show undo/redo effect on screen.

解决方案

Finally i get it and able to have smooth drawiwith undo/redo features too. It was the drawBitMap method which was causing problems..

i removed (commented) the call to this [self drawBitmap] method everywhere.

i was calling this method in touchesEnded and in undo/redo methods. I felt no need of using this method , as it does the caching (to speed up drawing ) whenever user lifts his fingere from screen a new image is created and placed on screen and old one is deleted and user is having an illusion that he is drawing continuously. But this caching is only needed in extreme situation when you really want to improve the performance (if you are going out of memory and your drawing starts becoming ugly).

So i decided to save this caching mechanism at some later stage and removed it. Though i was not able to find out why my undo/redo feature was not working with it , but i think when i had a new image cached and when it was placed on screen (when user lifts fingere) then it was creating problems as i have to retain last cached image (for undo/redo).

I will use caching at a later stage and will try to optimise my code as well.

Also remember to remove [myPath removeAllPoints]; this line from touchesEnded: method , other wise your drawing will get vanished as soon as you lift your fingere.

Hope this will help somebody. Here is the touchesEnded: modified method.

- (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;
}

Later i have added this feature to SmoothedBIView and its working very fine.

这篇关于无法通过平滑的自由手绘进行撤消/重做的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆