机器人(singletouch)绘图应用程序撤消方法不能正常工作 [英] android (singletouch) drawing app undo method not working properly

查看:195
本文介绍了机器人(singletouch)绘图应用程序撤消方法不能正常工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我工作的一个绘图应用程序,但面临着一些问题,撤消。的编码如下:

 公共类DoodleView扩展视图
{
    上下文context_new;    私有静态最终浮动TOUCH_TOLERANCE = 5;
    私人位图位图; //绘图区域显示或保存
    私人帆布bitmapCanvas; //用于绘制位图
    私人涂料paintScreen; //用来绘制位图到屏幕上
    私人涂料paintLine; //用来画线位图上    私人路径的mpath;
    私人的ArrayList<路径和GT;路径=新的ArrayList<路径>();
    私人的ArrayList<路径和GT; undonePaths =新的ArrayList<路径>();
    私人浮动MX,我的;   // DoodleView构造函数初始化DoodleView
   公共DoodleView(上下文的背景下,ATTRS的AttributeSet)
   {
       超(背景下,ATTRS); //通过上下文来查看的构造
       this.context_new =背景;       paintScreen =新的油漆(); //用于显示位图到屏幕上       //为画线设置初始显示设置
       paintLine =新的油漆();
       paintLine.setAntiAlias​​(真);画线//边缘光滑
       paintLine.setColor(Color.BLACK); //默认颜色为黑色
       paintLine.setStyle(Paint.Style.STROKE); // 实线       的mpath =新路径();
       paths.add(的mpath);   } //结束DoodleView构造

OnSizeChanged:

  @覆盖
   公共无效onSizeChanged(INT W,INT小时,INT oldW,诠释oldH)
   {
      super.onSizeChanged(W,H,oldW,oldH);
      DoodlzViewWidth = W;
      DoodlzViewHeight = H;      位图= Bitmap.createBitmap(的getWidth(),DoodlzViewHeight,Bitmap.Config.ARGB_8888);      bitmapCanvas =新的Canvas(位图);
      bitmap.eraseColor(Color.WHITE); //删除白色位图
   }

的onDraw:

  @覆盖
   保护无效的onDraw(帆布油画)
   {
       canvas.drawBitmap(位图,0,0,paintScreen);
       //每条路径目前正在拟订
       对于(路径P:路径){canvas.drawPath(P,paintLine);}
   }

onTouchEvent:

  @覆盖
   公共布尔onTouchEvent(MotionEvent事件)
   {
          浮X = event.getX();
          浮Y = event.getY();          开关(event.getAction())
          {
              案例MotionEvent.ACTION_DOWN:
                  touchStarted(X,Y);
                  无效();
                  打破;
              案例MotionEvent.ACTION_MOVE:
                  touchMoved(X,Y);
                  无效();
                  打破;
              案例MotionEvent.ACTION_UP:
                  touchEnded();
                  无效();
                  打破;
          }
          返回true;
    }

touchStarted:

 私人无效touchStarted(浮法X,浮法Y)
   {
       mPath.reset();
       mPath.moveTo(X,Y);
       MX = X;
       我= Y;
   }

touchMoved:

 私人无效touchMoved(浮法X,浮法Y)
   {
       浮DX = Math.abs(X - MX);
       浮DY = Math.abs(Y - 我的);
       如果(DX> = || TOUCH_TOLERANCE DY> = TOUCH_TOLERANCE)
       {
           mPath.quadTo(MX,MY,(X + MX)/ 2,(Y + MY)/ 2);
           MX = X;
           我= Y;
       }
   }

touchEnded:

 私人无效touchEnded()
   {
      mPath.lineTo(MX,我的);
      bitmapCanvas.drawPath(的mpath,paintLine);
      的mpath =新路径();
      paths.add(的mpath);
      Toast.makeText(的getContext(),touchEnded+ paths.size(),Toast.LENGTH_SHORT).show();
   }

撤消

 公共无效onClickUndo()
{
   Toast.makeText(的getContext(),撤消按钮$ P $之前pssed+ paths.size(),Toast.LENGTH_SHORT).show();
   如果(paths.size()大于0)
    {
       undonePaths.add(paths.remove(paths.size() - 1));
       Toast.makeText(的getContext(),撤消按钮$ P $后pssed+ paths.size(),Toast.LENGTH_SHORT).show();
       Log.i(毁灭,prePARE INVALIDATE);
       无效();
       Log.i(毁灭,FINISH INVALIDATE);
    }
   其他Toast.makeText(的getContext(),没什么可撤销+ paths.size(),Toast.LENGTH_SHORT).show();
}

问:

以上是从其他的例子来源网上搜索。不知道为什么需要设置path.reset(实施时) touchStarted

Q1。当我preSS的撤销按钮,它会正确显示面包取消按钮pressed,并报告 path.size( )为0,因此立即$ pviously画线p $是的不会被删除即可。我真的不知道为什么是0?不是它添加到路径数组了吗?怎么可以在code进行修改?

** code。考虑Android的开发者的意见后修改的!谢谢!!现在正确地显示path.size()。很抱歉的愚蠢错过!* 但是得出的previous线仍然不能被删除? =(

Q2。虽然app正常当手指在屏幕上移动,并显示立即行,当我preSS的撤消按钮,除了是previous线以上不除,线条进一步借鉴后pressing屏幕按钮不会显示出来,直到手指抬起。

答案Q2:
touchEnded()移动下面的2行 touchStarted()

  =的mpath新路径();
paths.add(的mpath);

 私人无效touchStarted(浮法X,浮法Y)
   {
       mPath.reset();
       的mpath =新路径();
       paths.add(的mpath);
       mPath.moveTo(X,Y);
       MX = X;
       我= Y;
   }   私人无效touchEnded()
   {
       mPath.lineTo(MX,我的);
       bitmapCanvas.drawPath(的mpath,paintLine); //提交路径,我们的屏幕外
       Toast.makeText(的getContext(),touchEnded+ paths.size(),Toast.LENGTH_SHORT).show();
   }

谢谢!


解决方案

更新和作品:


  1. 去除油漆paintScreen;

  2. 在的onDraw不要把 canvas.drawBitmap(位图,0,0,paintScreen); canvas.drawBitmap(位图, 0,0,paintLine);

     私人位图位图; //绘图区域显示或保存
    私人帆布bitmapCanvas; //用于绘制位图
    私人涂料paintLine; //用来画线位图上
    私人路径的mpath;
    私人的ArrayList<路径和GT;路径=新的ArrayList<路径>();
    私人的ArrayList<路径和GT; undonePaths =新的ArrayList<路径>();
    私人浮动MX,我的;
    私有静态最终浮动TOUCH_TOLERANCE = 4;// DoodleView构造函数初始化DoodleView公共DoodleView(上下文的背景下,ATTRS的AttributeSet)
    {
       超(背景下,ATTRS); //通过上下文来查看的构造
       this.context_new =背景;
       setFocusable(真);
       setFocusableInTouchMode(真);   //为画线设置初始显示设置
       paintLine =新的油漆();
       paintLine.setAntiAlias​​(真);画线//边缘光滑
       paintLine.setDither(真);
       paintLine.setColor(Color.BLACK); //默认颜色为黑色
       paintLine.setStyle(Paint.Style.STROKE); // 实线
       paintLine.setStrokeJoin(Paint.Join.ROUND);
       paintLine.setStrokeWidth(5); //设置默认线宽
       paintLine.setStrokeCap​​(Paint.Cap.ROUND); //四舍五入线两端   bitmapCanvas =新的Canvas();
       的mpath =新路径();
     } //结束DoodleView构造 //的方法OnSizeChanged创建应用程序后显示位图和帆布 @覆盖
     公共无效onSizeChanged(INT W,INT小时,INT oldW,诠释oldH)
     {
        super.onSizeChanged(W,H,oldW,oldH);
        DoodlzViewWidth = W;
        DoodlzViewHeight = H;
     } @覆盖 保护无效的onDraw(帆布油画)
     {
       对于(路径P:路径){canvas.drawPath(P,paintLine);}
       canvas.drawPath(的mpath,paintLine);
       Log.i(OnDRAWING,达成DRAW);
    }

    //启动触摸:处理触摸事件
         @覆盖

     公共布尔onTouchEvent(MotionEvent事件)
     {
          浮X = event.getX();
          浮Y = event.getY();      开关(event.getAction())
          {
              案例MotionEvent.ACTION_DOWN:
                  touch_start(X,Y​​);
                  无效();
                  打破;
              案例MotionEvent.ACTION_MOVE:
                 TOUCH_MOVE(X,Y);
                  无效();
                  打破;
              案例MotionEvent.ACTION_UP:
                  润色();
                  无效();
                  打破;
          }
          返回true;
    } 私人无效touch_start(浮法X,浮法Y)
     {
       undonePaths.clear();
       mPath.reset();
       mPath.moveTo(X,Y);
       MX = X;
       我= Y;
    }私人无效TOUCH_MOVE(浮法X,浮法Y)
    {
        浮DX = Math.abs(X - MX);
        浮DY = Math.abs(Y - 我的);
        如果(DX> = || TOUCH_TOLERANCE DY> = TOUCH_TOLERANCE)
        {
            mPath.quadTo(MX,MY,(X + MX)/ 2,(Y + MY)/ 2);
            MX = X;
            我= Y;
        }
    }私人无效touch_up()
    {
        mPath.lineTo(MX,我的);
        bitmapCanvas.drawPath(的mpath,paintLine); //提交路径,我们的屏幕外
        paths.add(的mpath);
        的mpath =新路径();
    }公共无效onClickUndo()
    {
       如果(paths.size()大于0)
        {
           undonePaths.add(paths.remove(paths.size() - 1));
           无效();
        }
       其他Toast.makeText(的getContext(),没有更多的撤销,Toast.LENGTH_SHORT).show();
    }


I am working on a drawing app but facing some undo problems. The coding is as follows:

public class DoodleView extends View 
{
    Context context_new;

    private static final float TOUCH_TOLERANCE = 5;
    private Bitmap bitmap; // drawing area for display or saving
    private Canvas bitmapCanvas; // used to draw on bitmap
    private Paint paintScreen; // use to draw bitmap onto screen
    private Paint paintLine; // used to draw lines onto bitmap

    private Path mPath; 
    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>();
    private float mX, mY;

   // DoodleView constructor initializes the DoodleView
   public DoodleView(Context context, AttributeSet attrs) 
   {
       super(context, attrs); // pass context to View's constructor
       this.context_new=context;

       paintScreen = new Paint(); // used to display bitmap onto screen

       // set the initial display settings for the painted line
       paintLine = new Paint();
       paintLine.setAntiAlias(true); // smooth edges of drawn line
       paintLine.setColor(Color.BLACK); // default color is black
       paintLine.setStyle(Paint.Style.STROKE); // solid line

       mPath = new Path();
       paths.add(mPath);

   } // end DoodleView constructor

OnSizeChanged:

   @Override
   public void onSizeChanged(int w, int h, int oldW, int oldH)
   {
      super.onSizeChanged(w, h, oldW, oldH);
      DoodlzViewWidth = w;     
      DoodlzViewHeight = h;

      bitmap = Bitmap.createBitmap(getWidth(), DoodlzViewHeight, Bitmap.Config.ARGB_8888);

      bitmapCanvas = new Canvas(bitmap);
      bitmap.eraseColor(Color.WHITE); // erase the BitMap with white 
   } 

onDraw:

   @Override
   protected void onDraw(Canvas canvas)  
   {
       canvas.drawBitmap(bitmap, 0, 0, paintScreen); 
       // for each path currently being drawn
       for (Path p : paths){canvas.drawPath(p, paintLine);}                
   } 

onTouchEvent:

   @Override
   public boolean onTouchEvent(MotionEvent event) 
   {          
          float x = event.getX();
          float y = event.getY();

          switch (event.getAction())
          {
              case MotionEvent.ACTION_DOWN:
                  touchStarted(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_MOVE:
                  touchMoved(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_UP:
                  touchEnded();
                  invalidate();
                  break;
          }
          return true;
    }

touchStarted:

   private void touchStarted(float x, float y) 
   {
       mPath.reset();
       mPath.moveTo(x, y);
       mX = x;
       mY = y;
   }

touchMoved:

   private void touchMoved(float x, float y) 
   {
       float dx = Math.abs(x - mX);
       float dy = Math.abs(y - mY);
       if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) 
       {
           mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
           mX = x;
           mY = y;               
       }
   }

touchEnded:

   private void touchEnded() 
   {
      mPath.lineTo(mX, mY);      
      bitmapCanvas.drawPath(mPath, paintLine);
      mPath = new Path();
      paths.add(mPath);
      Toast.makeText(getContext(), "touchEnded" + paths.size(), Toast.LENGTH_SHORT).show();
   }

Undo:

public void onClickUndo() 
{ 
   Toast.makeText(getContext(), "before undo button pressed " + paths.size(), Toast.LENGTH_SHORT).show();  
   if (paths.size()>0) 
    { 
       undonePaths.add(paths.remove(paths.size()-1));
       Toast.makeText(getContext(), "after undo button pressed " + paths.size(), Toast.LENGTH_SHORT).show();
       Log.i("UNDOING", "PREPARE INVALIDATE");
       invalidate();
       Log.i("UNDOING", "FINISH INVALIDATE");
    }      
   else Toast.makeText(getContext(), "nothing to undo" + paths.size(), Toast.LENGTH_SHORT).show();  
}

Question:

The above is sourced from other examples searched online. Dont know why need to set path.reset() when implementing touchStarted?

Q1. When I press the undo the button, it would properly show the toast undo button pressed, and reporting the path.size() being 0, and hence the immediately previously drawn line is not removed. I really dont know why it is 0?? Isnt it added to the path array already? How could the code be modified?

** code modified after taking android-developer's advice! Thanks!! It now correctly showing path.size(). Sorry for the silly missing out!* But the previous line drawn is still cannot be removed? =(

Q2. While the app is functioning properly when the finger is moving on the screen and showing the line immediately, When I press the undo the button, in addition to the above that previous line is not removed, the lines further draw to the screen after pressing the button will not show out until the finger is lifted.

answer to Q2: moving the below 2 lines from touchEnded() to touchStarted()

mPath = new Path();
paths.add(mPath);

.

   private void touchStarted(float x, float y) 
   {
       mPath.reset();
       mPath = new Path();
       paths.add(mPath);
       mPath.moveTo(x, y);
       mX = x;
       mY = y;
   }

   private void touchEnded() 
   {
       mPath.lineTo(mX, mY);      
       bitmapCanvas.drawPath(mPath, paintLine);// commit the path to our offscreen                   
       Toast.makeText(getContext(), "touchEnded" + paths.size(), Toast.LENGTH_SHORT).show();
   }

Thanks!!!

解决方案

updated and works:

  1. removed Paint paintScreen;
  2. in onDraw do not put canvas.drawBitmap(bitmap, 0, 0, paintScreen); or canvas.drawBitmap(bitmap, 0, 0, paintLine);

    private Bitmap bitmap; // drawing area for display or saving
    private Canvas bitmapCanvas; // used to draw on bitmap
    private Paint paintLine; // used to draw lines onto bitmap   
    private Path mPath; 
    private ArrayList<Path> paths = new ArrayList<Path>();
    private ArrayList<Path> undonePaths = new ArrayList<Path>();
    private float mX, mY;
    private static final float TOUCH_TOLERANCE = 4;    
    
    // DoodleView constructor initializes the DoodleView
    
    public DoodleView(Context context, AttributeSet attrs) 
    {
       super(context, attrs); // pass context to View's constructor
       this.context_new=context;
       setFocusable(true);
       setFocusableInTouchMode(true);      
    
       // set the initial display settings for the painted line
       paintLine = new Paint();
       paintLine.setAntiAlias(true); // smooth edges of drawn line
       paintLine.setDither(true);
       paintLine.setColor(Color.BLACK); // default color is black
       paintLine.setStyle(Paint.Style.STROKE); // solid line
       paintLine.setStrokeJoin(Paint.Join.ROUND);
       paintLine.setStrokeWidth(5); // set the default line width
       paintLine.setStrokeCap(Paint.Cap.ROUND); // rounded line ends
    
       bitmapCanvas = new Canvas();
       mPath = new Path();            
     } // end DoodleView constructor
    
     // Method onSizeChanged creates BitMap and Canvas after app displays
    
     @Override
     public void onSizeChanged(int w, int h, int oldW, int oldH)
     {
        super.onSizeChanged(w, h, oldW, oldH);
        DoodlzViewWidth = w;       
        DoodlzViewHeight = h;           
     } 
    
     @Override
    
     protected void onDraw(Canvas canvas) 
     {         
       for (Path p : paths){canvas.drawPath(p, paintLine);}  
       canvas.drawPath(mPath, paintLine);
       Log.i("OnDRAWING", "REACH ON DRAW");        
    } 
    

    // START TOUCH: handle touch event @Override

     public boolean onTouchEvent(MotionEvent event) 
     {            
          float x = event.getX();
          float y = event.getY();
    
          switch (event.getAction())
          {
              case MotionEvent.ACTION_DOWN:
                  touch_start(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_MOVE:
                 touch_move(x, y);
                  invalidate();
                  break;
              case MotionEvent.ACTION_UP:
                  touch_up();
                  invalidate();
                  break;
          }
          return true;
    }
    
     private void touch_start(float x, float y) 
     {
       undonePaths.clear();
       mPath.reset();
       mPath.moveTo(x, y);
       mX = x;
       mY = y;
    }
    
    private void touch_move(float x, float y) 
    {
        float dx = Math.abs(x - mX);
        float dy = Math.abs(y - mY);
        if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) 
        {
            mPath.quadTo(mX, mY, (x + mX)/2, (y + mY)/2);
            mX = x;
            mY = y;
        }
    }  
    
    private void touch_up() 
    {
        mPath.lineTo(mX, mY);      
        bitmapCanvas.drawPath(mPath, paintLine);// commit the path to our offscreen  
        paths.add(mPath);
        mPath = new Path(); 
    }
    
    public void onClickUndo() 
    { 
       if (paths.size()>0) 
        { 
           undonePaths.add(paths.remove(paths.size()-1));
           invalidate();
        }      
       else Toast.makeText(getContext(), "nothing more to undo", Toast.LENGTH_SHORT).show();  
    }
    

这篇关于机器人(singletouch)绘图应用程序撤消方法不能正常工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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