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.
Related
I have recently encountered the problem that the canvas.drawArc()-method on my locked SurfaceView canvas significantly slows down the loading and resuming time of my app. I am absolutely sure that the annotated line of code mainly causes this problem, but I also attached some other code that might be relevant for you.
The thread which is created in the surfaceView.surfaceCreated()-method (probably less relevant):
while(true) {
while (!running()) {
try {
sleep(50);
} catch (Exception ignore) {
}
}
try {
surfaceView.canvas = holder.lockCanvas();
synchronized(holder) {
surfaceView.draw();
}
} catch(Exception ignore) {
} finally {
try {
holder.unlockCanvasAndPost(surfaceView.canvas);
} catch(Exception ignore) {
}
}
}
And the actual draw()-method which is most likely to cause the problem:
// other draw methods, including a bitmap, ovals from float[]-Arrays, paths and text
Paint paint = new Paint();
paint.setColor(0x33d0d5c9);
paint.setStyle(Paint.Style.FILL);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
ArrayList<float[]> particles = new ArrayList<>();
while(particles.size() < 200) {
particles.add(new float[]{x1, y1, x2, y2});
}
// completely removing the following loop prevents the problem
for(float[] p : particles) {
// draw overlapping particles on the canvas (a path would affect the look)
canvas.drawOval(new RectF(p[0], p[1], p[2], p[3]), paint);
}
I would really appreciate your suggestions on how to optimize my code to work properly.
EDIT: My solution based on lukasrozs answer
final Canvas canvas = canvas;
Thread particleThread = new Thread(new Runnable(){
#Override
public void run() {
RectF rect = new RectF();
for(float[] p : particles) {
rect.set(p[0], p[1], p[2], p[3]);
canvas.drawOval(rect, paint);
}
}
});
particleThread.start();
// some stuff
try {
particleThread.join();
} catch(Exception ignore) {
}
My best guess is that you are creating to many objects in your onDraw method. Try to move the creation of the particles outside (in the constructor, or just do it once), and only set the new x,y and size values in the draw method.
Creating new objects in the onDraw method also increases the risk of the garbage collector to be triggered, so its best to avoid it ...
You don't have to use ArrayList and float[] at all. Also, you don't have to initialize/construct new RectF every time.
// other draw methods, including a bitmap, ovals from float[]-Arrays, paths and text
Paint paint = new Paint();
paint.setColor(0x33d0d5c9);
paint.setStyle(Paint.Style.FILL);
paint.setFlags(Paint.ANTI_ALIAS_FLAG);
RectF rect = new RectF();
for(int i = 0; i < 200) {
rect.set(x1, y1, x2, y2);
canvas.drawOval(rect, paint);
}
If you can, you should execute this method in another thread.
new Thread(new Runnable(){void run(){
// draw all the ovals on canvas
context.runOnUiThread(new Runnable(){void run(){
// this will be executed in main thread when drawing finishes
}});
}}).start();
I don't want to post the entire program on here because that would be too much, but I will post snippets of it and detail where they came from so you have an idea.
Problem: For my class project, I am making a typical space invaders game. When a missile hits a ship an explosion gif is played. The gif only loops once (not continuous). The when the missile hits the alien craft, the gif plays just fine for the first spaceship. However, when I shoot a missile at the second or third,etc, ship the gif does not play again. I believe that it is just playing the last frame of the gif from what I have researched. Is there a way to either reload the gif image to play each time the missile is hits or is there another way to do this?
Here is the link to the image: http://postimg.org/image/v2lljr7cb/
Here is some code:
I have a class called Boom, where the explosion is happening. Here is the code in that class:
public void draw(Graphics2D g2d) {
g2d.drawImage(getEnemyImg(), x, y, null);
}
public Image getEnemyImg() {
ImageIcon ic = new ImageIcon("src/Boom.gif");
return ic.getImage();
}
I then have another class called GameFrame where everything happens. In it, there are these lines of code specially for the explosion. Here is the code from this class:
static ArrayList<Boom> booms = new ArrayList<Boom>();
public void paint(Graphics g) {
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
ImageIcon ic = new ImageIcon("src/BackGround.jpg");
g2d.drawImage(ic.getImage(), 0, 0, null);
player.draw(g2d);
for (int i = 0; i < booms.size(); i++) {
Boom bm = booms.get(i);
bm.draw(g2d);
}
Enemy e = new Enemy(200, 400);
}
#Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
player.update();
for (int i = 0; i < booms.size(); i++) {
Boom bm = booms.get(i);
bm.update();
}
checkEnd();
repaint();
}
public static void addBoom(Boom bm) {
booms.add(bm);
}
public static void removeBoom(Boom bm) {
booms.remove(bm);
}
public static ArrayList<Boom> getBoomList() {
return booms;
}
Finally, here is where the explosion is being added. This happens when the missile hits the alien space craft. This is happening in the Enemy class. Here is the code:
public void checkCollisions() {
for (int i = 0; i < GameFrame.getMissileList().size(); i++) {
Missile m = GameFrame.getMissileList().get(i);
if (getBounds().intersects(m.getBounds())) {
GameFrame.removeEnemy(this);
GameFrame.removeMissile(m);
GameFrame.addBoom(new Boom(m.getX() -40, m.getY()- 60));
for(int j = 0; i <GameFrame.getBoomList().size(); i++){
Boom bm = GameFrame.getBoomList().get(j);
}
}
}
}
I apologize for the wall of text. My professor was unsure of how to do this so I was hoping to get some help from here.
If you have any time to spare, your ideas would be helpful. Thank you.
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.
I'm just trying to draw a circle on the spot where I touch the screen. When I touch the screen, a circle is drawn there, but then when I touch the screen somewhere else a new circle is drawn (the old one is supposed to appear there, not a new one). Does anyone understand why this is happening? Code:
Thread class:
public class GameThread extends Thread{
private SurfaceHolder sHolder;
private DrawingSurface dSurface;
private boolean okToRun;
Paint redPaint = new Paint();
public int x, y;
boolean myTouchEvent(MotionEvent event){
int touch = event.getAction();
switch(touch){
case MotionEvent.ACTION_DOWN:
x = (int) event.getX();
y = (int) event.getY();
}
return true;
}
public GameThread(SurfaceHolder holder, DrawingSurface surface){
sHolder = holder;
dSurface = surface;
redPaint.setARGB(255, 255, 0, 0);
}//GameThread()
public void setOkToRun(boolean status){
okToRun = status;
}//setOkToRun()
public void run(){
while(okToRun){//gameloop
Canvas canvas = null;
try{
canvas = sHolder.lockCanvas(null);
synchronized(sHolder){
try{
canvas.drawCircle(x, y, 60, redPaint);
} catch (Exception e){
}
}
} finally {
if (canvas != null) {
sHolder.unlockCanvasAndPost(canvas);
}
}
}
}//run()
}
Here are the relevant methods of my surfaceview class:
#Override
public boolean onTouchEvent(MotionEvent event) {
return drawingThread.onTouchEvent(event);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
drawingThread = new GameThread(getHolder(), this);
drawingThread.start();
drawingThread.setOkToRun(true);
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
radius += 10;
drawingThread.setOkToRun(false);
try {
drawingThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
TO BE CLEAR: I want to draw a single circle, and have it appear wherever I tap the screen. It does not do that. Can you tell why that is the case in this code?
I hope I am right that you need to draw a circle at the place where the screen was touched and the problem is that circles from previous touches still appear on the screen.
In this case the problem is, that you are drawing circles on canvas without clearing it. Canvas is represented in a memory as a array. When you call Canvas.drawCircle() part of memory is rewritten by an image of circle. When you do it repeatedly, the canvas contains more circles which are being drawn on the screen. You need to repaint the whole canvas before you draw a new circle. It can be done by calling the method Canvas.drawColor() before calling the method Canvas.drawCircle(). It clears the whole Canvas with selected color.
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());