Does Canvas object changes between two different runs of onDraw() method? - java

I'm trying to understand if onDraw method of the same View/Custom View object runs with exactly the same Canvas object?
I tried to examine an implementation when from my code i'm calling onDraw method (and without using invalidate method). in the onDraw method i'm saving the Canvas object that is an input parameter of this method as an object member, and than using this object. I can't understand if it a valid operation, or a Canvas object is different between two different runs of onDraw method and saving it won't serve me?
Code (can be an inner Class):
private class CustomView extends View
{
Canvas canvas;
#Override
public void draw(#NonNull Canvas canvas)
{
this.canvas = canvas;
Path path = new Path();
if (Utils.isLangRTL())
{
path.moveTo(lineColor.getWidth(), 0);
path.lineTo((float) 0.9 * lineColor.getWidth(), lineColor.getHeight());
path.lineTo(0, lineColor.getHeight());
path.lineTo((float) 0.1 * lineColor.getWidth(), 0);
path.lineTo(lineColor.getWidth(), 0);
canvas.drawPath(path, new paint());
}
}
and than calling the code from somewhere (UI Thread):
customView.onDraw(customView.canvas);

Related

libgdx, java - trying to call a .render() from another class

Hello I am trying to draw "whiteballoon" in main from a serperate class called whiteBalloon. The point is , whenever I call this class's method render() I want to be able to have multiple sprites on screen, clones of each other. The below code is giving me a null exception..
this is the class that i am calling from the main loop.
class whiteBalloon{
Sprite whiteballoon;
SpriteBatch batch;
OrthographicCamera camera;
public whiteBalloon(SpriteBatch batch){
}
public void create(){
batch = new SpriteBatch();
whiteballoon = new Sprite(new Texture("white_balloon.png"));
whiteballoon.setPosition(0, 0);
camera = new OrthographicCamera(Gdx.graphics.getWidth(),
Gdx.graphics.getHeight());
}
public void render(){
System.out.println("hey");
batch.begin();
whiteballoon.draw(batch);
batch.end();
}
}
and then i call it by using
whiteBalloon grumpface;
grumpface = new whiteBalloon();
grumpface.render();
You need to call grumpface.create() before grumpface.render() or just put create() method inside constructor:
public whiteBalloon(){
create();
}
Also your constructor requires a SpriteBatch object as argument, but you don't provide it later in code, so it uses default (empty) constructor instead of the one you created.

Bitmaps overlap when using canvas.drawBitmap

I recently started to learn about android and java and to practice I started to make a space invader-type game.
In order to draw all the images(player/enemy/etc) I've been using an overridden onDraw method and canvas.DrawBitmap(..). This is where my problem starts. Whenever I draw the images with their new X,Y coordinates, the previous bitmap is still on the canvas which makes everything overlap. Is there some way to refresh the canvas or just get rid of the "leftovers"(I don't even know what to call them). When I made this I was under the impression that I just move the 1 image across the screen but it looks like I was wrong.
This is the code I use to draw the player bitmap:
public void render(Canvas canvas){
//draw the player image
canvas.drawBitmap(_bmPlayerImg, (float) (_dX - (_iHalfWidth)),
(float)(_dY - (_iHalfHeight)), null);
}
The onDraw() method:
#Override
protected void onDraw(Canvas canvas) {
//draw the player
_player.render(canvas);
}//end method
The onDraw() method is called in a thread I use as my game timer every 50ms:
public Runnable runnable = new Runnable() {
#Override
public void run() {
canvas = null;
try {
canvas = surfaceHolder.lockCanvas();
synchronized(surfaceHolder){
//update the state of all objects in the game
gamePanel.update(canvas);
gamePanel.onDraw(canvas);
}
} finally {
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}//end if
}//end finally
handler.postDelayed(this, _iRepeatTime);
}
};
Any help is appreciated...I tried looking it up but I couldn't find anything.
Before you draw anything on the canvas:
//clear the canvas
canvas.drawColor(Color.TRANSPARENT, PorterDuff.Mode.CLEAR);
And now your canvas is clear and you can draw your character.
If your onDraw method was in an expanded view class and was triggered by you calling invalidate(), then the canvas would automatically clear itself. But you are manually calling it (looks like you are using a surface/texture view?), so you have to clear it manually.

LibGDX - Stage.setViewport(new Viewport()) black screen

For organization's sake, I use multiple scenes for my game and rather than having each scene have a constructor that receives a Viewport (my game is scalable), I would like to set each stage's viewport separate of the constructor, then after the viewport is set, add the actors. In the main class, it would happen like this:
public void setStage(Stage s)
{
if(currentStage != null)
currentStage.dispose();
currentStage = s;
currentStage.setViewport(view);
}
To make this go fluidly, each stage has an init method that is called within an overriden setViewport:
#Override
public void setViewport(Viewport v)
{
super.setViewport(v);
init();
}
However, all this gives me is a black screen... I have tried updating the camera and viewport, but no avail (note that the actors are having their render methods called).
Why am I getting this black screen and how do I fix it? If it's not possible I'll just revert to using the constructor.
If I understood correctly you want to do this:
Stage stage1 = new Stage();
stage1.getViewport().update(width, height);
rather than this:
Stage stage1 = new Stage (new StretchViewport(width, height)); // It doesn't have to be StretchViewport
In the first case (what you are trying to do) a ScalingViewport will be costructed automatically for you with dimensions of the Gdx.graphics and an orthographic camera and acts like a StretchViewport. Why not using the second case directly where you pass the viewport you want. You can always alter your viewport whenever you want by calling stage1.getViewport().update(width, height);
or by calling stage1.setViewport(width, height, false); in older Libgdx versions.
Viewport has changed recently so if you can extend Viewport class to Override the update method maybe you can achieve what you want:
public class ViewportExtendClass extends StretchViewport{
public ViewportExtendClass(float worldWidth, float worldHeight) {
super(worldWidth, worldHeight);
}
#Override
public void update (int screenWidth, int screenHeight, boolean centerCamera) {
super.update(screenWidth, screenHeight, centerCamera);
// DO YOUR INITIALIZATION HERE
}
}
From your main class you create new stage :
Stage stage1 = new Stage (new ViewportExtendClass (width, height));
and then you call :
stage1.getViewport().update(width, height);
Like this you can alter stage viewport and re initialize your assets.
#Override
public void setViewport(Viewport v)
{
super.setViewport(v);
this.getViewport().update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), false);
Camera c = this.getViewport().getCamera();
c.position.set(c.viewportWidth/2, c.viewportHeight/2, 0);
init();
}
This works, but you should also be able to update the Viewport like that at the begin of your application, if you continue to use the same one. I set the position like that instead of centering because some of my Stages will be larger than the screen.

what does the super call for onDraw do in the SurfaceView callback method, example: super.onDraw(canvas)

what exactly does the super.onDraw() do in this example?
what if i leave it out, does it change what will happen when onDraw method is called?
class Preview extends SurfaceView implements SurfaceHolder.Callback {
// onDraw is a callback method of the SurfaceView class
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// more code to implement some action when this method is called
} // end onDraw method
} // end Preview class
EDIT: i just found an excellent question and answer to help clarify the purpose of supercall, When NOT to call super() method when overriding?
If you look at SurfaceView's source code, you see that it extends View and it doesn't override the onDraw() method, so it's View's onDraw() method that is being called.
Now look at View's onDraw() method:
/**
* Implement this to do your drawing.
*
* #param canvas the canvas on which the background will be drawn
*/
protected void onDraw(Canvas canvas) {
}
It doesn't do anything. So calling super.onDraw() in your class will do nothing.
It does nothing ) SurfaceView's onDraw is View's onDraw and it's empty. But there is no guarantee that it always be empty. So you better call it if you do not have some reasons not to call.
It calls the method onDraw() in the class SurfaceView.
Generally speaking, not in your specific case:
Since it is a base class there in the super class implementation, basic things like borders,colors, or whatever sets to the canvas object you passed.
If you don't want them write on your own here.

Java JComponent.getGraphics() always returns null

I am trying to an object that functions as a button but uses images for display. My problem is that when call getGraphics() it returns null. I have been searching allover the place and cannot find why?
My code for the constructor where it dies at is...
public class ImageButton extends javax.swing.JComponent implements java.awt.event.MouseListener {
private static BufferedImage DEFAULTBUTTON;
private BufferedImage button;
private Graphics g;
public ImageButton(){
//Call the constructor for JComponent
super();
//Grab Graphics
g = this.getGraphics();
//Find the default images
try{
InputStream image;
image = this.getClass().getClassLoader().getResourceAsStream("DefaultButton.png");
DEFAULTBUTTON = ImageIO.read(image);
System.out.println("Default image FINE");
}catch(IOException e){
System.out.println("Default image fail");
}
button = DEFAULTBUTTON;
//Add listener for things like mouse_down, Mouse_up, and Clicked
this.addMouseListener(this);
//Draw the Default button
g.drawImage(button, 0, 0, this);
}
I would LOVE it you could give me help or point it the right direction.
You shouldn't call getGraphics() on a component. Instead, you should override the paintComponent(Graphics) method, and do the painting in this method, using the Graphics object passed as argument.
getGraphics will return null in the constructor as the component will not be visible at the time of creation. For custom painting in Swing override the paintComponent(g) method instead. There the Graphics handle will always be properly initialized.
Here is an example
For more read Performing Custom Painting

Categories

Resources