I want to have an image moving around in a JFrame. How do I do this without it blinking all the time. I've got a tip to use DoubleBuffering, but I don't know how it works. Any ideas?
Printable View
I want to have an image moving around in a JFrame. How do I do this without it blinking all the time. I've got a tip to use DoubleBuffering, but I don't know how it works. Any ideas?
All subclasses of JComponent can take advantage of double buffering. The idea behing double buffering is that it takes longer for a component to render it's individual parts on screen than it does for a rectangular area copy to take place. If the former occurs with multiple refreshes the human eye is likely to catch the compontent in the process of being drawn, and it may appear to flicker. With the latter the screen is usually updated as fast as the monitor can refresh itself.
This has an advantage. Why you might ask? Area copies are always faster becuase they are performed by the operating system or the graphics card of the computer. At this level they are commonly referred to as "bit block transfers" or BitBLTs.
To set double buffering for a component just pass true to the
doubleBuffered(boolean b) method. It's default value is false.
Still not sure how to use it in this case, cause neither JFrame or Image is a JComponent.
Here's the code:
Any suggestions?Code:import javax.swing.*;
import java.awt.Graphics.*;
import java.awt.*;
public class Testthread extends JFrame implements Runnable
{
private int x = 100,y = 100;
private Image testImage;
public Testthread()
{
setTitle("Test");
setSize(300,300);
testImage = Toolkit.getDefaultToolkit().getImage("image.gif");
setVisible(true);
}
public void run()
{
for(x = 100; x < 200; x++)
{
repaint();
try
{
Thread.sleep(100);
}
catch(InterruptedException e)
{
}
}
}
public void paint(Graphics g)
{
super.paint(g);
g.drawImage(testImage,x,y,this);
}
}
Sure they are.Quote:
Posted by CreoN
Still not sure how to use it in this case, cause neither JFrame or Image is a JComponent.
For awt:
java.lang.Object ---> java.awt.Component ---> java.awt.Container ---> java.awt.Window ---> Dialog and Frame.
For swing:
JDialog and JFrame just extend Dialog and Frame
But it's not a JComponent, it's a Component cause it doesn't extend JComponent (or am I wrong again..? :)) But anyway, could you write some example code? Tried a few things, and I can't get it to work...
Yeah it's kind of weird. I have some documentation that says
JFrame and JDialog Extend their awt counterparts but they also extend JComponent which extends Component .
So im trying to visualize the class structure. So this would mean that JFrame and JDialog extend JComponent(abstract super class) and also extend their awt counterparts. but anyway......
Yeah, im not to sure what would be the best way to go. I really dont know too much about screen painting, using the canvas class, or any type of graphics rendering, so i dont think that im really the person to ask.
Does the code you have run?
From the Java API:
You mean the one I posted before? It works fine, but the image blinks each time it's repainted.Code:java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Container
|
+--javax.swing.JComponent
java.lang.Object
|
+--java.awt.Component
|
+--java.awt.Container
|
+--java.awt.Window
|
+--java.awt.Frame
|
+--javax.swing.JFrame
You just need to start the thread, and it should work.
Yeah im not quite sure what to do in your situitation. Image dosent have the doubleBuffered(boolean b) method and i dont think that tiere is a JImage class. And your right JFrame doesnt extend JComponent. So im not sure :confused:
JFrame extends Frame that extends Window that extends Container - Component - Object. Not JComponent. JComponent is a subclass from Container, and not associated with JFrame in any way. Subclasses of JComponent is:
Therefore JFrame, doesn't have setDoubleBuffered as method.Code:AbstractButton, BasicInternalFrameTitlePane, JColorChooser,
JComboBox, JFileChooser, JInternalFrame,
JInternalFrame.JDesktopIcon, JLabel, JLayeredPane, JList,
JMenuBar, JOptionPane, JPanel, JPopupMenu, JProgressBar,
JRootPane, JScrollBar, JScrollPane, JSeparator, JSlider, JSplitPane,
JTabbedPane, JTable, JTableHeader, JTextComponent, JToolBar,
JToolTip, JTree, JViewport
I think i know what you could do. hold on. :p
Try this. it might work. Just translate the code to your own.
Code:import java.applet.*
import java.awt.*;
public class BufferingApplet extends Applet {
private Image bufferImage;
private Graphics imageGfx;
private Color color1 = Color.grey;
private Color color2 = Color.black;
public void init(){
// Create an Image
bufferImage = createImage(getSize().width, getSize().height);
// Get the graphics context associated with the Image
imageGfx = bufferImage.getGraphics();
}
public void paint(Graphics gfx){
// swap colors
Color temp = color2;
color2 = color1;
color1 = temp;
// clear buffer image
imageGfx.setColor(getBackground());
imageGfx.fillRect(0,0,getSize().width, getSize().height);
// render graphics in the buffer image
imageGfx.setColor(color1);
imageGfx.fillArc(20,0 // top left hand corner
50, 50 // width, height
30,300); // start angle, sweep angle
imageGfx.setColor(color2);
imageGfx.drawString("Come and Play!", 0,60);
// Display the buffer image, passing applet as the ImageObserver
gfx.drawImage(bufferImage, 50, 20, this);
}
// override update to reduce flickering
public void update(Graphics gfx){
paint(gfx);
}
}
Im not sure if the previous code will work for you. I think that you could use some of the techniques in the code to get the results that you wanted.
If you look at the paint method, it actualy does the rendering
in the buffer image using the buffer images graphics context, and it displays it on the screen using the drawImage() method
on the applets graphics context. Screen updating will always result in rendering graphics in the buffer image first, and then displaying the buffer image in the component.
The rendering works great, and it moves without flickering. Well, not great actually... it works, but I get these errors during runtime:
Code:Exception occurred during event dispatching:
java.lang.NullPointerException
at Testthread.paint(Testthread.java:61)
at sun.awt.RepaintArea.paint(Unknown Source)
at sun.awt.windows.WComponentPeer.handleEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
How much of the code did you actually use? It's for an applet and i know that's not what you wanted. So im not too sure where the problem is occuring. :)
I used most of the code. Like
bufferImage = createImage(getSize().width, getSize().height);
// Get the graphics context associated with the Image
imageGfx = bufferImage.getGraphics();
and that stuff.
I made a try-catch around it all, so I don't get those errors anymore. It seems as I only get them the first time the code is executed (it's in a loop).
I will have a couple of friends look at the code, so it'll work out. Thanks for all the help!
interesting :confused: Yeah graphics are not my forte. sorry :(
i wish i could be of further assistance. :p