Minirock
Minirock

Reputation: 666

Draw and erase circle into canvas

i'm pretty newbie with android, so I don't know if this issue is basic or not.

I want to draw circle into a canvas every N seconds.

Looking for tutorials, I succeed drawing a circle into a canvas. But then the issue appeared. How can I erase a circle I have drawn previously.

The way I am doing it might be bad, in fact, I just draw an other circle (but white). That means, each iteration I draw a white circle in order to erase the previous one. ANd then the new circle in blue.

It's perfectly working on the first iterations...but as soon as I start drawing circle on places where I have already draw a circle...things starts to be wrong...its like if by drawing again some of the previously erased circles appeared again.

I don't really know how to explain it.

You can see what happen executing this peace of code.

My game activity launcher

public class GameActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Float max = new Float(200.42);
        ArrayList<Float> liste_test = new ArrayList<Float>();
        liste_test.add(new Float(36.8));
        liste_test.add(new Float(147.8));
        liste_test.add(new Float(97.8));
        liste_test.add(new Float(max));
        liste_test.add(new Float(10));
        setContentView(new ExampleSurfaceView(this,liste_test,max));
    }
}

My ExampleSurfaceView I use to draw circle using data 'normalized' from the list.

public class ExampleSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
    // Le holder
    SurfaceHolder mSurfaceHolder;
    // Le thread dans lequel le dessin se fera
    DrawingThread mThread;

    int oldPosition_x;
    int oldPosition_y;

    ArrayList<Integer> valeurs_capteurs;
    int nb_valeurs;

    public ExampleSurfaceView (Context context,ArrayList<Float> donees_capteur, Float max) {
        super(context);
        this.valeurs_capteurs=normalise(donees_capteur,max);
        this.nb_valeurs=this.valeurs_capteurs.size();
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);

        mThread = new DrawingThread();
    }

    //pour récupérer des données uniforme peu importe le capteur
    public ArrayList<Integer> normalise(ArrayList<Float> donnees, Float max){
        valeurs_capteurs = new ArrayList<Integer>();
        for (Float donnee : donnees) {
            int donnee_normalized= (int)((donnee/max)*100);
            valeurs_capteurs.add(donnee_normalized);
        }
        return valeurs_capteurs;
    }


    protected void onDraw(Canvas canvas,int nb) {
        //dessinez ici
        super.onDraw(canvas);
        Paint paint = new Paint();
        paint.setStyle(Paint.Style.FILL);

        int index = nb%(nb_valeurs-1);

        System.out.println(index);

        //On calcule une position à partir des données du capteur
        int circlePositionX = 60+this.valeurs_capteurs.get(index);
        int circlePositionY = 60+this.valeurs_capteurs.get(index);


        //initialisation au premier draw
        if(nb==0){
            oldPosition_x=circlePositionX;
            oldPosition_y=circlePositionY;
        }

        //effacer l'andien cercle
        paint.setColor(Color.WHITE);
        canvas.drawCircle(oldPosition_x,oldPosition_y, 50,paint);
        System.out.println("Erase in "+oldPosition_x+" - "+oldPosition_y);

        oldPosition_x=circlePositionX;
        oldPosition_y=circlePositionY;

        //dessiner le nouveau cercle
        paint.setColor(Color.BLUE);
        canvas.drawCircle(circlePositionX, circlePositionY, 50,paint);
        System.out.println("Draw in "+circlePositionX+" - "+circlePositionY);

    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        // Que faire quand le surface change ? (L'utilisateur tourne son téléphone par exemple)
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        mThread.keepDrawing = true;
        mThread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        mThread.keepDrawing = false;

        boolean joined = false;
        while (!joined) {
            try {
                mThread.join();
                joined = true;
            } catch (InterruptedException e) {}
        }
    }

    private class DrawingThread extends Thread {
        // Utilisé pour arrêter le dessin quand il le faut
        boolean keepDrawing = true;

        @SuppressLint("WrongCall")
        @Override
        public void run() {

            int nb=0;
            while (keepDrawing) {
                Canvas canvas = null;

                try {
                    // On récupère le canvas pour dessiner dessus
                    canvas = mSurfaceHolder.lockCanvas();
                    // On s'assure qu'aucun autre thread n'accède au holder
                    synchronized (mSurfaceHolder) {
                        // Et on dessine
                        onDraw(canvas,nb);
                        nb+=1;
                    }
                } finally {
                    // Notre dessin fini, on relâche le Canvas pour que le dessin s'affiche
                    if (canvas != null)
                        mSurfaceHolder.unlockCanvasAndPost(canvas);
                }

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {}
            }
        }
    }
}

When I'm looking on the prints, the data seems to be logic, I erase and print to the good place...but still the issue remains...Obviously I'm doing something wrong, but I can't figure what it is after multiple search. Thanks for your assistance.

Upvotes: 1

Views: 1087

Answers (1)

Benoit TH
Benoit TH

Reputation: 631

If you're trying to delete everything that's on your canvas you can just call this at the beginning of your onDraw method:

canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR)

Also, in order to draw a canvas 60 times per second, you can just call invalidate() at the end of your onDraw function. You probably don't need a surface, just use a custom View instead of SurfaceView, this way it will be cleared automatically every time onDraw is called

Upvotes: 1

Related Questions