JPanel repaint does not work - java

I am developing a graphic project in java using swing and awt libraries. I am looking for a method that allow me to draw very fast on my JPanel. I tried various methods: overriding paintComponent, calling repaint(x, y, width, heigth).. But in all cases i have to repaint ALL the screen! I have a background and a small image in front of it that changes every few time. i am looking for a method that allow me to paint on the screen only the small image, i don't need to repaint the background too, because it is always the same, and the small image is always at the same coords. for example in C++ i painted the background and then i only painted the small images in front of it using putimage (graphics.h), so that it was very very fast. Do someone have some tips?

I've had some experience with game programming and usually a JPanel is used as canvas. Now to paint on it you would write a simple loop which continuously buffers an image and later paints it to the screen. So on initialisation you create a Graphics or Graphics2D object which is passed to a buffer() method. After painting a BufferedImage with the Instance of Graphics, some paint() method paints the BufferedImage to the screen.
When only painting the background once, previously drawn images will still be visible. If all your images are the same size, you don't have to bother but I still recommend repainting your background as well.
Have a look at the book Killer Game Programming In Java for further information, it's a great reference.

Tips:
Paint static images to a BufferedImage and then draw that within the paintComponent using Graphics#drawImage(...)
You do know that the repaint(...) method is overloaded and that one overload can accept a Rectangle parameter, limiting the area of repainting.

Related

Swing: Update Graphics every millisecond?

I created a little sketchpad program with basic GUI. I used the paintComponent method. I want to update the graphic being drawn every millisecond. That way, the user can see what they're about to draw before they release the mouse click.
For example, if I'm drawing a rectangle, I want to see the rectangle while I'm drawing it.
If you're confused as to what exactly I'm talking about, open MS Paint and click on the rectangle tool. Draw a rectangle. Notice how it updates continuously, as opposed to after you release the mouse.
I figured that there must be some way I can get it to update my graphics every millisecond. What is the best way to go about doing this? Sorry if this is an easy question, I'm new to Swing! :)
Well you don't update every millisecond.
You use a MouseMotionListener and you update every time a mouseDragged event is generated to redraw the Rectangle.
Check out Custom Painting Approaches for two approaches on how to do this.
The examples show how to draw multiple rectangles by either:
Adding Objects to a List and then repainting each object every time the component is repainted
Painting directly onto a BufferedImage and the just painting the BufferedImage.

Relationship between BufferedImage, Graphics, and Canvas for games

I am a fairly new programmer and I am trying to make a very basic game using Java where you just move a sprite around the screen. What I have accomplished so far is make a SpriteSheet class that loads in my sprite sheet and saves a BufferedImage of the spritesheet as a field of that class and a Sprite class that will get a subimage(the sprite itself) from this field and saves it as a field in the Sprite class. I've tested this and it all works like it should. I understand this may not all be typical or the "correct", efficient way of doing things. I'm ok with figuring that out on my own but my problem now is understanding the relationship between BufferedImage, Graphics, and Canvas. I saw a tutorial where a guy saved his sprite as a BufferedImage and used this to create a Graphic. He then painted this Graphic onto a Canvas and added the Canvas to his JFrame. He also fit a BufferStrategy in there somehow connected to his Graphics, and I don't understand that at all. Whenever I try to adapt his method for my purposes, it never works. I've looked over the javadocs countless times for these things and I get them individually, but I just can't seem to understand how they fit together to accomplish my goals.
So in short: can anyone explain how BufferedImage, Graphics, and Canvas all fit together in the context of displaying a sprite for a 2D game, and how is a BufferStrategy used? Appropriate and relevant methods? Will this method be appropriate for rendering moving sprites around 15 fps? etc... My problem does not come from a lack of research or lack of knlowedge necessarily but more from a lack of understanding.
Thank you very much and any advice is greatly appreciated!
BufferedImage is a Image type, which has the capacity to be modified from within the code, but, it has no means by which it can paint it self to the screen.
Canvas is a AWT (heavy weight) container which is typically used for providing activate painting access via it's BufferStrategy. This is displayed to the screen.
Graphics is a abstract graphical library designed to make it easier to perform cross platform renderering.
The Canvas, via it's BufferStragegy provides access to a Graphics instance, which allows you to paint to the Canvas (and by extension, the screen). You use this Graphics context to paint the BufferedImage
A Canvas by itself can't be displayed on the screen, it must be first contained within a window of some type, like java.awt.Frame.
Essentially, the frame shows the user the Canvas, the Canvas provides access to the graphics hardware via the BufferStrategy and Graphics context and the BufferedImage provides a generalised representation of an image/image data which can be painted to the Graphics context (of the Canvas)
Maybe you should start by having a look at the JavaDocs for Canvas, BufferStrategy, BufferStrategy and BufferCapabilities and 2D Graphics for some examples

Best way to avoid redrawing an entire maze?

I'm working on a project for maze generation using Java, swing, and Java2D. I'm fairly new to Java2D so please excuse me if this question is newbish.
Basically, I have a successfully generated maze. I wish to draw this maze on a custom JPanel that I've set up and properly overridden PaintComponent on. The problem I have now is I currently have the ability to draw the maze, but every time I repaint it disappears. I've solved this by having it redraw the maze every time repaint() is called but this seems horribly inefficient. Since the maze doesn't change why should I have to redraw it?
So my question is this: is there any way to "cache" the drawing of the maze so I don't have to waste cycles redrawing it every time? I can see redrawing it every time for exceptionally large mazes being a major source of slow downs.
Thank you!
Draw the maze to a BufferedImage. Then in your paintComponent() method just paint the BufferedImage. Swing will determine whether the entire maze or just parts of it need to be repainted.
For an example painting onto a BufferedImage see the DrawOnImage example from Custom Painting Approaches.
If the maze never changes, you can initially draw it into a BufferedImage. You can use your same code you wrote for overriding paintComponent by creating a BufferedImage and calling image.createGraphics() on it to get a Graphics2D object. Any painting you do to the Graphics2D object returned from createGraphics() is added to the BufferedImage. You may have to extract your previous drawing code just for the maze into its own function which takes a Graphics2D object and draws to it.
Once you have your maze drawn into the BufferedImage, you can use any of the drawImage() functions in Graphics or Graphics2D. This avoids having to redraw the maze: now you are just drawing the already rendered image.

Rectangle fill using image

Using AWT, how do you import an image into a rectangle you have drawn? I want to assign the background to that particular rectangle only.
Set the Rectangle as the clipping region.
Draw the image at a point so (part of) it is inside the clipping region.
Clear the clip.
Draw the rectangle.
As seen in this answer (the shape here is of text, but same principle applies).
The most common approach is to override the the paint method in your component. Have a look at Graphics.drawImage(). Example: Drawing an Image
If you decide to move to Swing, you can take advantage of Swing's optimizied painting model, overriding paintComponent instead of paint.
See: Performing Custom Painting

Java 2D Graphics Rectangles

I'm attempting to make a Java Applet that will allow me to draw a graph data structure in a canvas. I will do this by clicking where I want to create nodes, and clicking the nodes to connect them. The problem is I cannot get the paint() method to behave correctly. I add new nodes to the graph (and squares on the canvas) inside the mousePressed(MouseEvent e) method using,
Graphics g = this.getGraphics();
g.setColor(Color.blue);
g.fillRect(e.getX(), e.gety(), 40, 40);
Everything works fine, until I resize the window, and then all the filled rectangles vanish. I overrided the paint method to just an empty method, but the same thing still happens. I can't add the fillRect commands inside paint() because I don't know what rectangles exist until the user interacts with it using the mouse.
How can I use g.fillRect() inside the mouse listener methods and make them stick?
The problem is the place you're drawing to isn't persistant. At any moment, you can lose everything you've drawn to it. The paint(Graphics) method is called when this happens. You'll either need to repaint the entire picture every time this happens, or you'll need to set aside a canvas to draw to and copy the contents to your applet's Graphics as needed.
Here's how to create and draw to an image:
http://java.sun.com/docs/books/tutorial/2d/images/drawonimage.html
Then, in your paint method, use your Graphics' drawImage(...) method to display the image you've created.
I don't know if I'm reading this correctly, but why not just store the location of the last click in a variable to be painted later, when the paint() method is called?
You've got to override the window resize action listener and call repaint inside of it.
The Graphics is temporary. When a region gets dirty, it will be repainted.
The best way is to create a BufferedImage, paint to it on mousePressed and call repaint.
When paint is called, draw the Image onto the passed Graphics Object. This way you don't need to store the Rectangles and you got a buffer which will improve performance.

Categories

Resources