I have a quite simple animation, a text in a big font moving continuously (pixel by pixel) to the left. The text is first converted to an image, then a timer task is started which repeatedly (every 10-20 ms) decrements the x coordinate of the image by 1, and does a repaint().
This program shows a strange behavior on some systems. On my PC with a nVidia card it runs smoothly. On my Vaio notebook, on a BeagleBoneBlack and on a friend's Mac it stutters heavily. It appears to pause for a while, then jump to the left about 10 pixels, pause again and so on.
What stumps me is the fact that on these systems the animation only stutters if you don't touch the mouse. As long as you move the mouse cursor within the window, no matter how slowly, or drag the window itself around, the animation runs perfectly smooth!
Can anybody explain this? Here is the program:
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import java.util.*;
class Textimg extends JComponent
{
String str;
Font font;
int x = 0;
final int ytext = 136;
Image img;
public Textimg(String s)
{
str = s;
font = new Font("Noserif", Font.PLAIN, 96);
setLayout(null);
}
protected void paintComponent(Graphics g)
{
if (img == null)
{
img = createImage(4800, 272);
Graphics gr = img.getGraphics();
gr.setFont(font);
gr.setColor(Color.BLACK);
gr.fillRect(0, 0, 4800, 272);
gr.setColor(new Color(135, 175, 0));
gr.drawString(str, 0, ytext);
gr.dispose();
}
g.drawImage(img, x, 0, this);
}
public void addX(int dif)
{
if (isVisible())
{
x = x + dif;
Graphics g = getGraphics();
if (g != null) paintComponent(g);
}
}
}
public class Banner extends JFrame
{
StringBuffer buf;
int sleeptime = 10;
Banner(String path) throws IOException
{
setSize(new Dimension(480, 272));
setTitle("Java Test");
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLayout(null);
BufferedReader reader = new BufferedReader(
new InputStreamReader(new FileInputStream(path), "UTF-8"));
buf = new StringBuffer();
while (true)
{
String line = reader.readLine();
if (line == null) break;
buf.append(line);
}
final Textimg textimg = new Textimg(buf.toString());
add(textimg);
textimg.setBounds(0, 0, 480, 272);
final javax.swing.Timer timer = new javax.swing.Timer(200, new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
textimg.addX(-1);
}
});
timer.setDelay(sleeptime);
timer.start();
}
//----------------------------------------------------------------------
public static void main(String[] args) throws Exception
{
new Banner(args[0]).setVisible(true);
}
}
Try calling this method when you are done drawing:
Toolkit.getDefaultToolkit().sync();
This flushs the graphics buffer which some systems like Linux use. See the Javadoc: http://docs.oracle.com/javase/7/docs/api/java/awt/Toolkit.html#sync()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With