Kevin04PT
Kevin04PT

Reputation: 9

Multi-threading in the same Canvas

Well, I'll try to explain exactly what I pretend:

I want to draw a bitmap in a canvas in random positions according to the coordinates of the screen on touch, and I want a message(text) to be displayed everytime the user touches the screen.

So, if a draw the text in the same thread than I do for the bitmap, it will appear and dissapear right after, and I want it to stay in the screen for a few seconds and the dissapear. My first idea was to use Thread.sleep(), but for that I have to create a thread only for the text, or I will mess with the Bitmap too.

I've been trying to use multithreading in the same canvas, but I don't know how. Can someone please explain to me...

That's some of the code i've got so far:

private void init() {
        // CREATE SURFACEHOLDER AND ADD THIS CLASS AS HIS CALLBACK
        enemyHolder = getHolder();
        enemyHolder.addCallback(this);

        scoreHolder = getHolder();
        scoreHolder.addCallback(this);

        hasSurface = false;

    }

public void resume() {

        if (surfaceViewThread == null) {
            surfaceViewThread = new SurfaceViewThread(); // CREATE A NEW
                                                            // THREAD
            if (hasSurface)
                surfaceViewThread.start(); // START OUR THREAD
        }

        if (secondThread == null) {
            secondThread = new SecondThread();

            if (hasSurface)
                secondThread.start();
        }

    }



public void surfaceCreated(SurfaceHolder holder) {
        hasSurface = true;

        if (surfaceViewThread != null)
            surfaceViewThread.start();

        if (scoreShow == 1) {

            if (secondThread != null)
                secondThread.start();
        }
    }

// THREAD

    private final class SurfaceViewThread extends Thread {
        private boolean done;

        SurfaceViewThread() {
            super();
            done = false;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            SurfaceHolder surfaceHolder = enemyHolder;

            while (!done) {

                Canvas canvas = surfaceHolder.lockCanvas();

                canvas.drawColor(Color.WHITE);

                canvas.drawBitmap(enemy1, enemy1X, enemy1Y, null); // DRAW
                                                                    // FIRST
                                                                    // ENEMY




    // SECOND THREAD

    private final class SecondThread extends Thread {
        private boolean done;

        SecondThread() {
            super();
            done = false;
        }

        @Override
        public void run() {
            // TODO Auto-generated method stub
            super.run();
            SurfaceHolder surfaceHolder = scoreHolder;

            while (!done) {

                Canvas canvas = surfaceHolder.lockCanvas();

                Paint paint = new Paint();
                paint.setColor(Color.BLACK);

                canvas.drawText("xD", 50, 50, paint);

                surfaceHolder.unlockCanvasAndPost(canvas);

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                scoreShow = 0;

            }

        }

Upvotes: 0

Views: 2867

Answers (2)

Simon
Simon

Reputation: 14472

Here's some incomplete pseudo code to do what you've described. There are plenty of good examples around for each of these elements to help you fill in the blanks.

public class MyCustomView extends View {

     int touchPointX;
     int touchPointY;

     private String mText;

     public MyCustomView(Context context) {

         // do initialisation stuff

     }

     public setText(String text){
         mText = text;
         this.invalidate();
     }

     @Override
     public void onDraw(Canvas canvas) {

        canvas.save();

        super.onDraw(canvas);

        canvas.drawBitmap(touchPointX, touchPointY, bitmap)

        if (!mText.equals(""){
            canvas.drawText(touchPointX, touchPointY + 10, mText)
        }

        canvas.restore();
    }

}

public class MyActivity extends Activity implements OnTouchListener{

     private Handler mHandler = new Handler(); 
     private MyCustomView mCustomView;

     @Override
     protected void onCreate(Bundle savedInstanceState) {
           mCustomView = (MyCustomView) findViewById(r.id.myCustomView);
     }

     @Override
    public boolean onTouch(View v, MotionEvent rawEvent) {

           // get x and y of touch
           mCustomview.touchPointX = x;
           mCustomview.touchPointY = y;
           mCustomView.setText("Screen touched");

           // clear the text after 5 seconds
           mHandler.postDelayed(clearText, 5000);


           // redraw the view
           mCustomView.invalidate();

    }

    private void clearText(){mCustomView.setText("");}

}

Upvotes: 0

Simon
Simon

Reputation: 14472

Do you need to use a SurfaceView? It seems like a hard work way of doing things.

I've just done something similar by creating a custom view class and overriding the onDraw method. Then use canvas.save() and canvas.restore(). Here's the relevant bits of my onDraw.

@Override
public void onDraw(Canvas canvas) {

    canvas.save();

    // scale the canvas
    canvas.scale(scaleFactor, scaleFactor); //, mid.x, mid.y);

    // and translate...
    canvas.translate(translateX / scaleFactor, translateY / scaleFactor);

    super.onDraw(canvas);

    // draw the lights
    for(Light light:lights){
        if (light.isOn){
            canvas.drawCircle(light.getX(),light.getY(), light.getDiameter() / scaleFactor,light.paint);
        }
    }

    canvas.restore();
}

The lights are turned on and off by a separate thread back in the activity which has inflated the view. They stay on screen as long as they are on.

Cheers

Upvotes: 1

Related Questions