I'm extremely new to Android development, but I have lots of experience with Java. What I'd like to know is how to independently draw on a View using a Canvas object.
What I want is an Android equivalent of this Java code:
BufferedImage img = new BufferedImage(100, 100, BufferedImage.TYPE_INT_ARGB);
Graphics g = img.getGraphics();
g.drawImage(whateverImage, 0, 0, null);
g = frame.getGraphics(); /*just pretend 'frame' is a JFrame that we're using*/
g.drawImage(img, 0, 0, 100, 100, null);
Basically all that code does is make a blank bitmap image, draw on that image, then draw the bitmap onto a JFrame to display it.
I'm aware that Android doesn't use BufferedImage or Graphics, but I believe that the Android pseudo-equivalents are Bitmap and Canvas, respectively.
The problem is that when I have code that like this:..
Bitmap guy = BitmapFactory.decodeResource(getResources(), R.drawable.guy);
Canvas c = new Canvas(Bitmap.createBitmap(100, 100, Bitmap.Config.ARGB_8888));
c.drawBitmap(guy, 0, 0, null);
...I take it that the same concept of a blank bitmap being created and then drawn on occurs. However, I don't know how to then draw the Canvas onto a View, SurfaceView, or some other method that will display it on my device's screen.
It's important to note that I do not want to #Override onDraw and use it to draw my graphics, as I would like to control the drawing independently using some sort of thread loop.
If I did not provide enough information or my question is nonsensical, feel free to either ask me about it or ignore it. Any help is greatly appreciated.
Also, if anybody has any tips, tutorials, references, or anything else to better my understanding of layouts, views, etc. that would be greatly appreciated as well. Like I said, I am very inexperienced and trying to learn.
EDIT: Now working. Thanks :) https://i.stack.imgur.com/ugWlu.png
The only way to draw onto a View is to override onDraw. What you can do though is draw to an in memory bitmap (like you do here) in any other function, then draw the bitmap to the screen in onDraw. Just do
public void onDraw(Canvas canvas) {
canvas.drawBitmap(inMemoryBitmap, 0, 0, paint);
}
Related
I was wondering how I would use something like a bufferstrategy in a Java Applet.
I want to draw something like an image
gfx.drawImage(frame, 0, 0, width, height, null);
to my applet but I am getting white flashes due to the graphics drawing to the screen not being buffered.
Any help would be greatly appreciated!
Edit: I have a thread that is repainting this image
Edit 2: The image is constantly changing so I need to repaint it each time it changes
Ah, so the public void update(Graphics g) method doesn't have white flashes due to the graphics drawing to the screen not being buffered. But the paint method does. Odd.
I'm developing a little graphic engine using Canvas in JavaFX. In some point I had to render an off screen image, and then print it on my primary canvas using its GraphicContext.
I'm using this code right now:
private Canvas offScreenCanvas;
private GraphicsContext offScreenGraphic;
private SnapshotParameters parameters;
private WritableImage offScreenImage;
[...]
offScreenCanvas = new Canvas(WIDTH, HEIGHT);
offScreenGraphic = offScreenCanvas.getGraphicsContext2D();
parameters = new SnapshotParameters();
parameters.setFill(Color.TRANSPARENT);
[...]
offScreenImage = offScreenCanvas.snapshot(parameters, offScreenImage);
graphic.setGlobalBlendMode(BlendMode.HARD_LIGHT);
graphic.drawImage(offScreenImage, 0, 0);
graphic.setGlobalBlendMode(BlendMode.SRC_OVER);
My problem is the method snaphot() takes too much time, ~14ms, in each execution. I need to update the canvas at least at 60fps, so this consumes practically all the time I have to draw.
Is there another way to get an Image or WritableImage from a canvas? Maybe another different process?
This is another method to obtain a visual equivalent result, without reduce performance.
I have used java.awt clases, instead of JavaFX clases. The creation of a java.awt.image.BufferedImage offers the possibility to get a java.awt.Graphics2D where you can draw using other methods. The main problem here is that draw big images consumes a lot of time using this libraries, but you can create a scaled image. In my case, I have created a quarter-size BufferedImage, and I have drawn all the objects using that scale factor.
At the end of the draw process, just convert the BufferedImage, to a javafx.scene.image.Image, using:
SwingFXUtils.WritableImage toFXImage(BufferedImage bimg, WritableImage wimg);
Then print it on the main canvas using:
graphic.drawImage(Image image, 0, 0, WIDTH, HEIGHT);
To fill all the canvas with the image.
Finally, the scale factor is configurable, so if you need a detailed image, just use a higher value. For me, a 25-percent-size image is enough because I am drawing gradients. Now, it takes 1-3ms to draw the image, this is much better than before.
Hope it helps someone.
In J2ME, only a screen or a canvas can be displayed at a time. The screen can have multiple objects inside it (textfield, form, etc.) while a canvas can only hold a gamecanvas.
The question is: Is it possible to have multiple game canvases in one canvas?
I'm trying to display two at the same time, one at the top and one at the bottom.
I'd like to repaint the bottom canvas without repainting the top.
Thank you in advance! Any form of help will be appreciated! :)
No, you can only display one Canvas or GameCanvas object at a time.
But: If you're asking about having 2 Canvas objects, because you need to update 2 parts of the screen independent of each other, you can do that by using 2 Image objects.
Simply get the Graphics object of each Image with Image.getGraphics();
Then you can draw onto each image.
And finally draw both images on the canvas (or just one of them, if you only want to update one part of the screen).
Example using GameCanvas:
Image topImage = Image.createImage(width, height);
Image bottomImage = Image.createImage(width, height);
Graphics topG = topImage.getGraphics();
Graphics bottomG = bottomImage.getGraphics();
Graphics g = getGraphics(); // Get graphics of the GameCanvas
drawStuffOn-topG();
drawStuffOn-bottomG();
g.drawImage(topImage, 0, 0, g.TOP|g.LEFT);
g.drawImage(bottomImage, 0, halfScreenHeight, g.TOP|g.LEFT);
flushGraphics();
No, you use just one canvas, but repaint only the bits that have changed using
Canvas.repaint(int x, int y, int w, int h);
i´m trying to make a game, but im stuck on the drawing.....
i make a custom surfaceView (with a draw() and update() methods) and my game loop(updating and drawing the view).
Everythong goes perfectly until i use the method Canvas.drawBitmap(Bitmap, Rect src, Rect dst, Paint p), becuase when i try to draw, for example :
Canvas.DrawBitmap(bitmap, null, new Rect(100, 100, 200, 150), null);
it doenst draw anything!! but here is the wearest part, if i put sumething like this:
Canvas.DrawBitmap(bitmap, null, new Rect(0,0,100,150), null);
it draw it perfectly as it has to be!!!! and if i put something like this:
Canvas.DrawBitmap(bitmap, null, new Rect(50,0,100,150), null);
it forms like limits, i mean, thas everything over the(for example, becuase im not sure how many pixels) 100px height doesn´t apear!!! i have tried many ways, PLEASE!!! can you help me!!!
(PD: My native language is spanish, i sorry if my text have some issue.)
The last parameter to any Canvas#draw methods as an object of Paint class. Without it, Canvas cannot do any drawing.
Before you do any drawing, initialize a Paint object with Paint paint = new Paint() and pass it to the Canvas#draw method. Remember to null the Paint object when you're done drawing, as it takes up a lot of memory.
How does one go about doing this? Could somebody give me an outline?
From what I've found online, it seems like in my run() function:
create a bitmap
create a canvas and attach it to the bitmap
lockCanvas()
call draw(canvas) and draw bitmap into back buffer (how??)
unlockCanvasAndPost()
Is this correct? If so, could I get a bit of an explanation; what do these steps mean and how do I implement them? I've never programmed for Android before so I'm a real noob. And if it isn't correct, how DO I do this?
It's already double buffered, that's what the unlockCanvasAndPost() call does. There is no need to create a bitmap.
The steps from Android Developers Group say that you need a buffer-canvas, to which all the renders are drawn onto.
Bitmap buffCanvasBitmap;
Canvas buffCanvas;
// Creating bitmap with attaching it to the buffer-canvas, it means that all the changes // done with the canvas are captured into the attached bitmap
tempCanvasBitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
tempCanvas = new Canvas();
tempCanvas.setBitmap(tempCanvasBitmap);
// and then you lock main canvas
canvas = getHolder().lockCanvas();
// draw everything you need into the buffer
tempCanvas.drawRect.... // and etc
// then you draw the attached bitmap into the main canvas
canvas.drawBitmap(tempCanvasBitmap, 0, 0, drawView.getPaint());
// then unlocking canvas to let it be drawn with main mechanisms
getHolder().unlockCanvasAndPost(canvas);
You are getting the main buffer, which you are drawing into without getting different double-buffer canvas' on each holder's lock.