PDA

View Full Version : Java dynamic image on static background...




NewbieNerd
Jan 19, 2007, 01:07 PM
Anybody know anything about efficiently doing this? Namely, creating a Speedometer, so there is a needle that moves on top of a static background image of a dial. Right now, every time the needle moves, I have to do a full clear and redraw of the background (it's slightly transparent, but it fills in completely if I don't clear). I know that there is this clear(x,y,width,height) method, but that's not terribly useful unless you want to clear a rectangle.

Any wisdom to share?



jeremy.king
Jan 19, 2007, 02:30 PM
Are you using Swing to do this?

NewbieNerd
Jan 19, 2007, 02:34 PM
Are you using Swing to do this?

Yes, I am extending JPanel. Should I be doing AWT?

jeremy.king
Jan 19, 2007, 03:22 PM
Have you considered using JLayeredPane (http://java.sun.com/docs/books/tutorial/uiswing/components/layeredpane.html) and just repainting the needle component when you need to?

NewbieNerd
Jan 19, 2007, 03:34 PM
Have you considered using JLayeredPane (http://java.sun.com/docs/books/tutorial/uiswing/components/layeredpane.html) and just repainting the needle component when you need to?

Hmm, I've never noticed this JLayeredPane before, but it looks like it might be worth a try. Thanks man!

NewbieNerd
Jan 23, 2007, 06:30 PM
So I'm using a JLayeredPane now, with both the background and needle as JPanel subclasses. Each just overrides paintComponent(Graphics g) to paint their corresponding stuff (no clearing). I also set needle.setOpaque(false), and whenever the needle needs to change, I just call needle.repaint(), but when I do this, the background's paintComponent method gets called everytime, and if I don't actually redraw the background, it gets cleared, never to be seen again.

Anymore help for a GUI newb? :)

jeremy.king
Jan 24, 2007, 11:47 AM
So I'm using a JLayeredPane now, with both the background and needle as JPanel subclasses. Each just overrides paintComponent(Graphics g) to paint their corresponding stuff (no clearing). I also set needle.setOpaque(false), and whenever the needle needs to change, I just call needle.repaint(), but when I do this, the background's paintComponent method gets called everytime, and if I don't actually redraw the background, it gets cleared, never to be seen again.

Anymore help for a GUI newb? :)

http://java.sun.com/j2se/1.4.2/docs/api/javax/swing/JComponent.html#paintComponent(java.awt.Graphics)

"Further, if you do not invoker super's implementation you must honor the opaque property, that is if this component is opaque, you must completely fill in the background in a non-opaque color. If you do not honor the opaque property you will likely see visual artifacts."

Edit - after reading up on this a little more - from the JFC/Swing tutorial (http://java.sun.com/docs/books/tutorial/uiswing/)

"You can improve painting performance by making components opaque when possible, so that the Swing painting system doesn't waste time trying to paint behind these components. To make a Swing component opaque, invoke setOpaque(true) on the component."

So you may want to try it with the opaque property set to true.

Good Luck!

MarkCollette
Jan 24, 2007, 07:07 PM
Sorry, is it just the clock hand foreground image that uses transparency, or does the background image use transparency as well? And if so, what's behind that?

NewbieNerd
Jan 25, 2007, 11:22 AM
Sorry, is it just the clock hand foreground image that uses transparency, or does the background image use transparency as well? And if so, what's behind that?

Just the clock hand...the background image does use a transparent color (via alpha setting), but there is nothing else behind them, though perhaps this entire image may be placed on top of something else that has a background.

rickb
Jan 25, 2007, 02:33 PM
You can make sure the animation looks good by using double buffering by drawing the background and needle to an offscreen Graphics object and then paint the entire image once. Google up some applet double buffering examples

MarkCollette
Jan 25, 2007, 02:42 PM
Just the clock hand...the background image does use a transparent color (via alpha setting), but there is nothing else behind them, though perhaps this entire image may be placed on top of something else that has a background.

Umm, what? In the first 4 words of your post you say that only the clock hands, and then immediately after you say that the background image does in fact use transparency? So, if you set the background color of the component that you're drawing on to vivid pink, will that pink show through or not?

Have you tried overriding the JComponent's paintComponent method, and making it do a Graphics.clearRect(), then drawing the background image, then drawing the foreground clock hand image? Does it flicker for you? An alternative it to create an offscreen image, do a Graphics.fillRect() on it, draw the two images to it, and then just blit that one image to the component, which should eliminate the artifacting. There's a couple classes that can help with this, including BufferedImage, VolatileImage, and BufferStrategy.

You could optimise it slightly by only clearing and blitting over the quadrants that the clock hand was in and now is in.