Проблема с видом на поверхность - PullRequest
1 голос
/ 14 апреля 2011

У меня проблема с мерцанием. Вот мой код.

public class Tutorial2D3 extends Activity {

Panel panel;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    panel = new Panel(this);
    setContentView(panel);
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    menu.add(1, 1, 1, "Clean Canvas");
    return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onMenuItemSelected(int featureId, MenuItem item) {
    panel.cleanCanvas();
    return true;
}

class Panel extends SurfaceView implements SurfaceHolder.Callback {
    TutorialThread thread;
    Bitmap icon;
    int iconWidth;
    int iconHeight;
    int touchX;
    int touchY;
    int mCount = 0;

    public Panel(Context context) {
        super(context);
        icon = BitmapFactory
                .decodeResource(getResources(), R.drawable.icon);
        iconWidth = icon.getWidth();
        iconHeight = icon.getHeight();
        getHolder().addCallback(this);
        thread = new TutorialThread(getHolder(), this);
        setFocusable(true);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        int x = touchX - (iconWidth / 2);
        int y = touchY - (iconHeight / 2);
        if(mCount>0) {
            canvas.drawColor(Color.BLACK);
            mCount--;
        }
        canvas.drawBitmap(icon, (x > 0 ? x : 0), (y > 0 ? y : 0), null);    
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
        // TODO Auto-generated method stub

    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        thread.setRunning(true);
        thread.start();
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        thread.setRunning(false);
        do {
            try {
                thread.join();
                retry = false;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } while (retry);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
            touchX = (int) event.getX();
            touchY = (int) event.getY();
            break;
        case MotionEvent.ACTION_MOVE:
            touchX = (int) event.getX();
            touchY = (int) event.getY();
            break;
        case MotionEvent.ACTION_UP:
            break;
        default:
            break;
        }
        return true;
    }

    private void cleanCanvas() {
        mCount = 2;
    }
}



class TutorialThread extends Thread {
    private SurfaceHolder _surfaceHolder;
    private Panel _panel;
    private boolean _run = false;

    public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
        _surfaceHolder = surfaceHolder;
        _panel = panel;
    }

    public void setRunning(boolean run) {
        _run = run;
    }

    @Override
    public void run() {
        Canvas c;
        while (_run) {
            c = null;
            try {
                c = _surfaceHolder.lockCanvas(null);
                synchronized (_surfaceHolder) {
                    _panel.onDraw(c);
                }
            } finally {
                if (c != null) {
                    _surfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
}

}

Нарисованное изображение мерцает. Похоже, что растровое изображение, нарисованное в одной точке, нарисовано на одной поверхности, а не на другой, поэтому оно выглядит как мерцание, растровое изображение, которое рисуется при прикосновении к action_up, готово, то есть представляет собой сплошное изображение и не мерцает. Может кто-нибудь, пожалуйста, помогите мне с этим. Спасибо

Ответы [ 3 ]

1 голос
/ 15 августа 2011

Одна вещь, которую вы могли бы сделать, чтобы смягчить это (и, в некотором смысле, противоречить Гийому :)), это использовать surfaceholder.lockCanvas (rectangle), где это только указанная прямоугольная часть холста, которая затем рисуется (но вы должны нарисовать каждый пиксель этого прямоугольника). Вот он, оторванный от образца LunarLandar:

@Override
    public void run() {
        while (mRun) {
            Canvas c = null;
            try {
                c = mSurfaceHolder.lockCanvas(Rectangle);
                synchronized (mSurfaceHolder) {
                    if (mMode == STATE_RUNNING) updatePhysics();
                    doDraw(c);
                }
            } finally {
                // do this in a finally so that if an exception is thrown
                // during the above, we don't leave the Surface in an
                // inconsistent state
                if (c != null) {
                    mSurfaceHolder.unlockCanvasAndPost(c);
                }
            }
        }
    }
1 голос
/ 19 апреля 2012

Я не прочитал все вашего кода, но я думаю, эта статья поможет.

Суть статьи в том, что мерцание происходит из-за двойной буферизации и может быть устранено путем рисования не для аргумента Canvas, а для растрового изображения, используемого в качестве холста, а затем для отрисовки этого растрового изображения в arg Canvas:

int myCanvas_w, myCanvas_h;
Bitmap myCanvasBitmap = null;
Canvas myCanvas = null;
Matrix identityMatrix;

@Override
public void surfaceCreated(SurfaceHolder holder) {

myCanvas_w = getWidth();
myCanvas_h = getHeight();
myCanvasBitmap = Bitmap.createBitmap(myCanvas_w, myCanvas_h, Bitmap.Config.ARGB_8888);
myCanvas = new Canvas();
myCanvas.setBitmap(myCanvasBitmap);

identityMatrix = new Matrix();
}

@Override
protected void onDraw(Canvas canvas) {

paint.setStyle(Paint.Style.STROKE);
 paint.setStrokeWidth(3);

 //int w = myCanvas.getWidth();
 //int h = myCanvas.getHeight();
 int x = random.nextInt(myCanvas_w-1);
 int y = random.nextInt(myCanvas_h-1);
 int r = random.nextInt(255);
 int g = random.nextInt(255);
 int b = random.nextInt(255);

 paint.setColor(0xff000000 + (r << 16) + (g << 8) + b);
 myCanvas.drawPoint(x, y, paint); // <--------- Here's where you draw on your bitmap

 canvas.drawBitmap(myCanvasBitmap, identityMatrix, null);
 // ^---------- And here's where you draw that bitmap to the canvas

}
1 голос
/ 14 апреля 2011

Когда вы рисуете в Canvas SurfaceView, вы должны всегда рисовать каждый пиксель поверхности .
Здесь вы не всегда очищаете Canvas в onDraw(), отсюда и мерцание.

...