java - 在 Canvas 中绘制并删除圆圈

标签 java android android-canvas

我是 android 的新手,所以我不知道这个问题是否是基本问题。

我想每隔 N 秒在 Canvas 上画一个圆。

通过查找教程,我成功地在 Canvas 中绘制了一个圆圈。但随后问题出现了。 我怎样才能删除我以前画的圆圈。

我这样做的方式可能不好,事实上,我只是画了另一个圆圈(但是是白色的)。这意味着,每次迭代我都会画一个白色圆圈以删除前一个。然后是蓝色的新圆圈。

它在第一次迭代时工作得很好......但是一旦我开始在我已经画了一个圆的地方画圆......事情开始出错......就像再次绘制一些先前删除的圆圈再次出现。

我真的不知道怎么解释。

您可以看到执行这段安静的代码会发生什么。

我的游戏 Activity 启动器

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

我的 ExampleSurfaceView 用于使用列表中“规范化”的数据绘制圆。

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

当我查看打印件时,数据似乎是合乎逻辑的,我删除并打印到正确的位置......但问题仍然存在......显然我做错了什么,但我不能'多次搜索后不知道它是什么。感谢您的帮助。

最佳答案

如果你想删除 Canvas 上的所有内容,你可以在 onDraw 方法的开头调用它:

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

此外,为了每秒绘制 Canvas 60 次,您可以在 onDraw 函数的末尾调用 invalidate()。您可能不需要表面,只需使用自定义的 View 而不是 SurfaceView,这样它会在每次 onDraw 时自动清除叫

关于java - 在 Canvas 中绘制并删除圆圈,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55090587/

相关文章:

android - 如何检查通行证是否已添加到Google钱包?

android - 使文本适合位图宽度

java - Netbeans 在保存后不应用更改

java - 每个 CollectionGroup 中的最新文档

java - JFrame 总是为 Action 监听器内的变量输出 null

android - android中的 bundle ID

java - 使按钮在 Canvas 上绘制的新路径上可见

Android Canvas 绘图不可见

java - 在 Java 类中调用 Kotlin 挂起函数

java - 许可基于 Java Web 的应用程序