Cannot call onDraw(Canvas canvas) with update() - java

I'm currently developing android and went into a very serious problem :
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.i("GAME", "onDraw Called");
for(int i = 0; i < totalEggNumbers -1; i++) {
if (egg[i].isKilled = false)
canvas.drawBitmap(image[egg[i].getEggNum()], egg[i].getX(), egg[i].getY() + 100, paint);
Log.i("GAME", "Something Drawn");
}
}
// called by thread
public void update() {
//Chance to make egg
Log.i("GAME", "Updated Game");
eggMaker.randomEgg(difficulty);
postInvalidate();
}
The onDraw never gets called and I cant find the log in logcat after I terminated the app, but when it is running, I could see one "onDraw Called" showing up and disappearing occasionally.
Im really desperate... I am using android view btw. Any way to call the onDraw method? I tried invalidate(); and no chance, please modify my code :)

Try to make your image as BitMap object before passing it to the drawBitMap methode
Bitmap bmp = BitmapFactory.decodeResource(
getResources(), image[egg[i].getEggNum());

Related

Using Android canvas in different class, debug crash errors

Just starting out with Android, canvas, the works. I have existing Java code that can draw shapes on a graphics object. I am trying to use that code in an Android app with Canvas. Basically, I'm trying to avoid refactoring all of my Java code to use Canvas explicitly. So I'm in the process of making my own "Graphics" object. All it should do is call the appropriate Canvas methods to draw the specified shape.
I've read multiple posts here about not being able to use the canvas object outside of the onDraw() method. From what I understand, you can't pass a canvas object to a different class and expect it to work correctly. But I also do not have a complete understanding of how all this works.
The app crashes in the Graphics class in the drawOval method. I've read up a log about all of this, but I haven't found a good answer as to why this specifically doesn't work.
I haven't been able to find a way to get crash logs in a java friendly way (aka a stacktrace). It just throws Fatal signal 11 (SIGSEGV), code 1, fault addr 0x130 in tid 1520.
Thanks! Let me know if more details are needed. Here's my code:
MainActivity
public class MainActivity extends AppCompatActivity {
MyCanvas canvas;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
canvas = new MyCanvas(this);
setContentView(canvas);
}
}
MyCanvas View
public class MyCanvas extends View {
Graphics graphics;
List<Shape> shapes;
public MyCanvas(Context context) {
super(context);
graphics = new Graphics();
shapes = new ArrayList<>();
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
graphics.setCanvas(canvas); //Sets the canvas object in the graphics class
for (Shape shape : shapes) {
try { //this is in a try/catch block for custom exception handling
//This just calls the specific shapes render method,
//in this case, a circle from the makeShape Method
//The graphics object then calls the specific shape to
//render on the canvas
shape.render(graphics, 0, 0);
} catch (ShapeException e) {
e.printStackTrace();
}
}
invalidate();
}
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
int x = (int) event.getX();
int y = (int) event.getY();
try { //this is in a try/catch block for custom exception handling
makeShape(x, y);
} catch (ShapeException e) {
e.printStackTrace();
}
invalidate();
case MotionEvent.ACTION_MOVE:
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL: {
break;
}
}
invalidate();
return true;
}
public void makeShape(int x, int y) throws ShapeException{
Point p = new Point(x, y);
Shape shape = new Circle(p, 50, 50);
shapes.add(shape);
}
}
Graphics
public class Graphics {
private Canvas canvas = null;
public Graphics() {
}
public void setCanvas(Canvas canvas) {
if (this.canvas == null) {
this.canvas = canvas;
}
}
public void drawOval(int x, int y, int width, int height) {
Paint paint1 = new Paint();
paint.setColor(Color.BLACK);
canvas.drawCircle(500, 500, 50, paint1); //App crashes here
}
}
You have a slight misunderstanding about being able to pass a Canvas to different classes. There is absolutely nothing wrong with that; passing a canvas to a class method is effectively the same as passing it to a regular function. Even storing the Canvas reference in a member variable isn't going to hurt anything.
HOWEVER, the above is only true with the understanding that the Canvas cannot be used outside the bounds of the draw()/onDraw() method. That is, any method that uses the Canvas must be called from within onDraw(), or a function called by onDraw(), etc.
This is because the Canvas is initialized (by the framework) immediately before onDraw(), in order to prepare for the current drawing operation. You might wish to think of it as initializing the Canvas with a Bitmap that will serve as the drawing output surface for this particular screen frame (which is not far from the truth). Once onDraw() has returned, the framework assumes your code will no longer be using it, and it can submit the output surface/Bitmap/etc. to the screen compositor for rendering, without fear of further alterations.
And, your approach is a good one, as a technique for adapting existing code to use a novel graphics object.
So, to address the crash: SIGSEGVs should never happen in normal Android development when you're not dealing (directly) with native/JNI routines. However, it occurs to me that you're not updating the Canvas object in the event it changes. This could be causing the crash (in native code, which is why you don't get a Java stack trace). You used an old Canvas after a newer one was given to you. Remove the condition if (this.canvas == null) and you should be fine.

onDraw Method not Called?

I am creating a custom view but the onDraw method is never being called. I tried doing this - setWillNotDraw(false) but it still doesn't work.
In fact, it doesn't even work after calling invalidate(). Here's my code -
public class Box extends View {
public Box (Context context) {
super (context);
init();
}
private void init() { // Initialize paint object
paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(mBoxColor);
setMeasuredDimension(200, 200);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawRect(100, 100, 200, 200, paint);
}
}
My activity code -
Box box = new Box(this);
Please help
In your MainActivity.java
use
setContentView(box);

canvas not drawing my required object

Program reach in loadpng block....it also prints the toast "it shold draw something but it dont draw circle but draw all the remaining stuff that is in my arraylist"
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
int p=0,cir=0,r=0,l=0;
if(load_png)
{
Toast_Display.long_message(getContext(),"should draw something");
canvas.drawCircle(300,300,100,get_paint(Color.WHITE,10));
invalidate();
}
for(int sequence : sequence_draw)
{
if(sequence==1)
{
int color = color_name.get(p);
int width = brush_width.get(p);
Path mypath = path_list.get(p);
Paint paint = get_paint(color,width);
canvas.drawPath(mypath, paint);
p++;
}
else if(sequence==2)
{
circle c = circles.get(cir);
canvas.drawCircle(c.getCx(),c.getCy(),c.getRadious(),get_paint2(c.getColor(),c.getWidth()));
cir++;
}
else if(sequence==3)
{
Rectangle rec = rectangles.get(r);
canvas.drawRect(rec.getCx(),rec.getCy(),rec.getDx(),rec.getDy(),get_paint2(rec.getColor(),rec.getWidth()));
r++;
}
else if(sequence==4)
{
Rectangle line = lines.get(l);
canvas.drawLine(line.getCx(),line.getCy(),line.getDx(),line.getDy(),get_paint(line.getColor(),line.getWidth()));
l++;
}
}
if(draw==true)
{
if(status.equals("circle"))
canvas.drawCircle(cx,cy,radious,get_paint2(current_circle_color,current_circle_width));
else if(status.equals("rec"))
canvas.drawRect(cx,cy,dx,dy,get_paint2(current_Rectngle_color,current_Rectngle_width));
else if(status.equals("line"))
canvas.drawLine(cx,cy,dx,dy,get_paint(current_line_color,current_line_width));
}
}
I don't know why it's not drawing my required object in load png block.... any help will be appreciated
Try removing the invalidate() call. It does not make sense to call invalidate() inside onDraw(), since it is invalidation that causes oDraw() to be called in the first place!
The fact that you are calling it in onDraw() could be causing Android to do something unexpected.

Draw in bitmap using canvas doesn't work in android view

I'm trying to use onDraw method and canvas to draw some items in a bitmap and cache it to draw it again and don't call onDraw again
This is part of my code :
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mCacheDrawing == null) {
mCacheDrawing = Bitmap.createBitmap(mScrollWidth, mScrollHeight, Config.RGB_565);
canvas.setBitmap(mCacheDrawing);
for (int i = 0; i < mIcons.size(); i++) {
prepareItem(canvas, paint, mIcons.get(i));
}
canvas.save();
} else {
canvas.setBitmap(mCacheDrawing);
}
}
The code is not working and show me an empty screen, can any one help me please?
EDIT : I have found the following post and it help me to solve the problem >> https://groups.google.com/forum/#!topic/android-beginners/6pO8SJN3CTY
and my working code now is following :
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mCacheDrawing == null) {
mCacheDrawing = Bitmap.createBitmap(mScrollWidth, mScrollHeight, Config.RGB_565);
mCanvas = new Canvas(mCacheDrawing);
for (int i = 0; i < mIcons.size(); i++) {
prepareItem(mCanvas, paint, mIcons.get(i));
}
}
canvas.drawBitmap(mCacheDrawing,new Rect (0,0, mScrollWidth, mScrollHeight), new Rect (0,0, mScrollWidth, mScrollHeight), paint);
}
Well i can't figure out functionality of your code as its a snippet from a section, But what I can figures out is the reason. quick check
If you trying to draw bitmaps from a view, make sure drawing cache is enabled/
canvas.drawBitmap , this is the API for drawing a Bitmap over a canvas and not setBitmap
you can use save and restore method of canvas accordingly.

Draw From Old Canvas - Android

I'm making an App that needs to be able to draw new graphics on top of the last set.
This is my current onDraw() method -
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
if(points.size() > 0) {
//do some stuff here - this is all working ok
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, linePaint);
}
}
Basically, I need to draw the new graphics as a layer on top of the last, so what I'm looking for is a way to carry the image of the last canvas to the current.
I have tried to figure it out myself using the canvas.setBitmap() method but it acts very funny.
Any help appreciated :)
P.S if it's needed, the the class extends SurfaceView and implements SurfaceHolder.Callback
Edit: This is what I have tried in the onDraw() method but it just force closes
if(bitmap != null) {
canvas.drawBitmap(bitmap, 0, 0, paint);
canvas.setBitmap(bitmap);
}
Found the answer myself :)
#Override
protected void onDraw(Canvas c) {
if(bitmap != null && canvas != null) {
canvas.drawLine(p1.x, p1.y, p2.x, p2.y, linePaint);
c.drawBitmap(bitmap, 0, 0, linePaint);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
canvas = new Canvas(bitmap);
canvas.drawColor(Color.WHITE);
}
Works exactly as intended, it creates the effect of drawing on top of the old canvas continuously
You will have to store the previous image persistently onto a ArrayList, and during ondraw, loop through the ArrayList to redraw all items.
something like this:
for (Graphic graphic : _graphics) {
bitmap = graphic.getBitmap();
coords = graphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}

Categories

Resources