Some animations (such as some gif files) only store in each frame the pixels that change from the previous frame. To draw these animations correctly, you have to paint the first frame, then paint the succeeding frames on top of them without erasing the previous frames. JPanels, however, always redraw the background when you call repaint(), erasing the previous frames. Is there a way to prevent a JPanel from redrawing the background? I've been told that calling super.paintComponent(g) in the JPanels paintComponent(Graphics g) method is what redraws the background, but I tried commenting that out and it lead to some strange behaviour, so I'm assuming it does more than just repaint the background.
I'd recommend to build your code upon the already existent code provided by the API instead of messing with it. Just store the image as BufferedImage. This allows you to display it using an ImageIcon, so it's an additional simplification. This allows you to update single pixels without any hassles with the API. If you absolutely insist on excluding the JPanel from the repaint-routine, this question might help.
In general:
Follow the conventional use of the API. If you want to permanently store data of an image, us a BufferedImage. JComponents are supposed to be entirely overridden every time the frame is updated.
Depending on your exact requirement there are two common approaches:
Draw on a BufferedImage and then display the BufferedImage
Keep an ArrayList of Objects you want to paint and paint all the Objects in the list every time paintComponent() is invoked.
Check out Custom Painting Approaches for more information and working examples of each approach.
Related
I am wondering whether I am able to use the paint method of Java's graphics class on something other than a JFrame--that is, no JFrames allowed. Is it possible?
Thanks in advance!
Graphics represents a graphic context, i.e. something you can draw on. In addition to GUI components like JFrame, JPanel etc. providing getGraphics() to access the visible gfx context, another common class that allows access to a gfx context is BufferedImage (or Image classes in general).
While painting on a visible GUI element immediately shows the results of the painting, using a BufferedImage allows you to perform the painting off screen into a buffer, and then painting the whole image at once (on a JFrame as you still need something visible) when you're ready to display the image. This is often used in animation and games when you need to avoid flickering for example.
I'm learning Java as part of my degree but its very brief but what ever I do I like to make sure I atleast have some understanding.
Until now anything that I want displayed on the screen is put into the paintcomponent method of the JPanel.
However, I have drawn out some parts of my layout which never change, and only a certain thing in the middle rotates.
I have a timer which calls repaint().
If I correct in thinking that everything including the components that never change are being removed and then redrawn and the whole paintcomponent method is being run every time.
To me I feel like I should (or there must be) a way where the static stuff is moved out / is only drawn once, and only the parts that I specifically want to be redrawing should stay in the paintcomponent method?
Is this correct or am I not fully understanding something?
I am assuming that you are not adding GUI components in the paintComponent method, right?
Components are not "removed" during a repaint
Better to put the stable part of any image into a single background BufferedImage and draw the BufferedImage in the paintComponent method. This can make for more efficient painting.
Consider calling an overload of repaint(...) that sets a bounding rectangle for the region to be painted.
So I wrote a small program for a class. I designed it as a JApplet inside an undecorated JFrame, not in a browser. Other than that, it's a simple drawing program of sorts. You click two points to draw the selected shapes, then it calls a repaint. The problem I'm having is that when you draw while the program has been moved to my secondary monitor, the entire JApplet seems to disappear, only displaying the drawn shape. It only disappears after the 2nd point is selected, so I presume it does this on repaint().
My secondary monitor is using the exact same brand and resolution, even color profile.
Any other technical details, I'm using Java 1.7 (Can't recall which update off the top of my head), Windows 8 Enterprise 64x, using Eclipse's Run button to test.
Thanks in advance for any help!
I am indeed calling getGraphics(); in the init() method of the JApplet..
That is the problem. The Graphics object is a transient thing that will be repainted the very next time the JVM thinks there is any need to do so. That might be triggered by:
Changing the size or location of the window.
Covering it with another program and then removing the covering app.
Adding new components or changing values that are displayed.
See Performing Custom Painting for more details on how to do what you are attempting to achieve. OTOH Swing has a JLabel that can show a BufferedImage. You can use the BufferedImage in the way you want. When it is updated, call repaint() on the label to see the effect.
I'm using Java Swing to make a GUI.
I need to present to the user some information printed on images (which are generated at run time as BufferedImage objects).
What I am doing: I put a JPanel on my JFrame, and when the system calls the paint(Graphics g) method I draw the image on g -> (g.drawImage(buffImg,0,0,null)).
The thing I do not like is: When I resize the frame, the image remains the same, I only expand the field of view. I'd like instead to make the image "stretch" with the frame when I resize it.
Is there an efficient way of doing it? (I thought I could create a new resized image, the size of the frame, each time I refresh the graphics, but I'm updating the image several times per second, so it would be a really heavy task..)
Change:
g.drawImage(BuffImg,0,0,null):
To:
g.drawImage(BuffImg,0,0,getWidth(),getHeight(),this):
I have been working on Java Swing for a while. I paint something(draw some basic shapes like circle,rectangle etc) on a JDesktopPane and once I resize the frame window that contains jDesktopPane or drag some other window over this frame, then the drawn shapes disappear. I use an object of the BufferedImage class so as to save the image. So Is there any way of preventing the shapes getting disappeared or repaint it when they disappear?
You need to make sure you are saving what you paint and repainting it each time in the paintComponent() method. This method is called automatically whenever a repaint is needed (for example: because of a resize).
I can only provide a guess since you've decided not to post the necessary code, but my suggestions are:
Don't get your Graphics object by calling getGraphics on a component. Instead,
Be sure to do your drawing in a class that subclasses a JComponent or one of its children (such as a JPanel).
draw your BufferedImage in the JComponent's paintComponent method immediately after calling super.paintComponent() in the same method. Use the Graphics object that is provided by the JVM and passed into the method's parameter.
To be sure that your paintComponent method's signature is correct, place an #Override annotation immediately before it. Otherwise if it is not correct, the JVM will probably not call it when you expect it to.
But also, please when asking a question here, try to give us enough information so we don't have to guess. Since your problem is graphics related, it would make sense to post your graphics-related code, right?