mrefive
mrefive

Reputation: 41

Android Canvas Thread going crazy

Hi guys:) I'm playing around trying to draw with my Mainthreat onto a canvas. Basicly my aim is to get a rectangle, and when I touch it it changes the color. In the onCreate Method I create the rectangle and call the quadr1.setColor Method to give it a fill. Then i start the threat. Now the draw Method should just recall the quadr1.draw method, and redraw the rectangle with the same color. When I touch quadr1 the threat calls now quadr1.setColor again, instead of quadr1.draw. This should give it a new color provided by my RandomColor class (Works fine).

The problem now: While the threat is running the canvas just disappears to show "whats behind" and reapears with the next action again. It looks like a torture method for epileptics. I read about double buffering, but cant find any solution myself. How can I get it to show the rectangle with its fill stable, and just changes when I touch it?

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

This is my quadr class: (Works fine, also the Random color class, testet it on several ways.)

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

Thanks a lot in advance for any help!!

Upvotes: 0

Views: 136

Answers (1)

Danail Alexiev
Danail Alexiev

Reputation: 7772

As far as I can see, the problem may be caused by colorChangeTouchInput.

You are setting it as true while intercepting the touch and, afterwards, you never set it to false again. This will lead to the draw() method never being called in the thread. I suggest you add colorChangeTouchInput = false after you call quadr1.setColor(canvas);.

Upvotes: 1

Related Questions