java - Android Canvas 线程变得疯狂

标签 java android multithreading canvas callback

大家好:)我正在尝试用我的 Mainthreat 在 Canvas 上画画。 基本上我的目标是得到一个矩形,当我触摸它时它会改变颜色。 在 onCreate 方法中,我创建矩形并调用 quadr1.setColor 方法为其填充。然后我就开始威胁。现在,draw 方法应该只调用 quadr1.draw 方法,并用相同的颜色重新绘制矩形。当我触摸quadr1时,威胁再次调用quadr1.setColor,而不是quadr1.draw。这应该给它一个由我的 RandomColor 类 提供的新颜色(工作正常)。

现在的问题:当威胁运行时, Canvas 会消失以显示“后面的内容”,并在下一个操作时再次出现。这看起来像是一种折磨癫痫患者的酷刑。我读到有关双缓冲的内容,但自己找不到任何解决方案。如何让它显示填充稳定的矩形,并且在触摸它时才发生变化?

public class GamePanel extends SurfaceView implements SurfaceHolder.Callback{

    private MainThread thread;
    private Canvas canvas;
    private Random random;
    private SurfaceHolder holder;
    RandomColor randomColor = new RandomColor();
    private boolean colorChangeTouchInput;

    private Quadr quadr1;

    public GamePanel(Context context){
        super(context);

        SurfaceHolder holder = getHolder();
        holder.addCallback(this);
        this.holder = holder;

        thread = new MainThread(holder);
        randomColor = new RandomColor();

        setFocusable(true);
    }

    class MainThread extends Thread{
        private boolean running;
        private SurfaceHolder surfaceHolder;

        public MainThread(SurfaceHolder surfaceHolder){
            this.surfaceHolder = surfaceHolder;
        }

        @Override
        public void run(){
            while(running) {
                canvas = null;
                try {
                    canvas = surfaceHolder.lockCanvas();
                    synchronized (surfaceHolder) {
                        if(colorChangeTouchInput=false) {
                            draw(canvas);
                        } else {
                            quadr1.setColor(canvas);
                        }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    if(canvas!= null){
                        surfaceHolder.unlockCanvasAndPost(canvas);
                    }
                }
            }
        }

        private void draw(Canvas canvas) {
            quadr1.draw(canvas);
        }
        public void setRunning(boolean b) {
            running = b;
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder){
        boolean retry = true;
        int counter =0;
        while(retry && counter <1000) {

            counter++;
            try {
                thread.setRunning(false);
                thread.join();
                retry=false;

            } catch(InterruptedException e){
                e.printStackTrace();
            }
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder){


        WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        int windowWidth = size.x;
        int windowHeight = size.y;

        canvas = null;
        canvas = holder.lockCanvas();

        quadr1 = new Quadr(0,0,windowWidth/2,windowHeight / 2, randomColor.getRandomColorA(), randomColor.getRandomColorR(), randomColor.getRandomColorG(), randomColor.getRandomColorB());
        quadr1.setColor(canvas);

        holder.unlockCanvasAndPost(canvas);

        thread.setRunning(true);
        thread.start();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        SurfaceHolder holderTouch = getHolder();

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                if(event.getX()>quadr1.getLeft() && event.getX()<quadr1.getRight() && event.getY()>quadr1.getTop() && event.getY()<quadr1.getBot()){
                    colorChangeTouchInput = true;  
                }             
        }      
        return super.onTouchEvent(event);
    }

    public boolean isColorChangeTouchInput() {
        return colorChangeTouchInput;
    }
}

这是我的四级类(class): (工作正常,随机颜色类也是如此,通过多种方式对其进行测试。)

public class Quadr extends GameObject {
    int left;
    int top;
    int right;
    int bot;
    int colorA[];
    int colorR[];
    int colorG[];
    int colorB[];
    int colorFixed;

    Paint paint = new Paint();
    Rect rect = new Rect();
    Random rnd = new Random();

    public Quadr(int left, int top, int right, int bottom, int colorA[], int colorR[], int colorG[], int colorB[]) {
        this.left=left;
        this.top=top;
        this.right=right;
        this.bot=bottom;
        this.colorA=colorA;
        this.colorR=colorR;
        this.colorG=colorG;
        this.colorB=colorB;

        rect.set(left, top, right, bottom);
    }

    public void setColor(Canvas canvas){
        int num = rnd.nextInt(3);
        colorFixed = num;

        paint.setStyle(Paint.Style.FILL);
    rnd.nextInt(256));
        paint.setARGB(colorA[num], colorR[num], colorG[num], colorB[num]);
        canvas.drawRect(rect, paint);
    }

    public void draw(Canvas canvas) {
        paint.setStyle(Paint.Style.FILL);
        paint.setARGB(colorA[colorFixed], colorR[colorFixed], colorG[colorFixed], colorB[colorFixed]);
        canvas.drawRect(rect, paint);

    }

    public int getLeft() {
        return left;
    }
    public int getTop() {
        return top;
    }
    public int getRight() {
        return right;
    }
    public int getBot() {
        return bot;
    }
}

提前非常感谢您的帮助!!

最佳答案

据我所知,该问题可能是由 colorChangeTouchInput 引起的。

您在拦截触摸时将其设置为true,之后,您再也不会将其设置为false。这将导致draw()方法永远不会在线程中被调用。我建议您在调用 quadr1.setColor(canvas); 之后添加 colorChangeTouchInput = false

关于java - Android Canvas 线程变得疯狂,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31703594/

相关文章:

android - 2D Picker 未进入环境光模式

.net - 是否使用 Sleep(),如果 Sleep() 不好,正确的方法是什么?

java - 如何杀死正在等待同步资源的线程?

java - 解码UTF问题?

android - 如何定义 NotificationChannel 是否被用户禁用(API 26)?

android - 在 android 中使用适配器的 FlowLayout

c# - 从另一个线程关闭表单

java - 洗牌 ImageView 位置

java - 如何在 TSPM 中禁用自定义 PIP 的缓存?

java - 嵌套集的 JPA Criteria 查询