java swing timer not precise enough?
hello java forums users. :p
recently been testing some more gui stuff. :p
and it came to my attention that the java swing timer isn't really that accurate...
i used a little program to test it... and it starts pretty good, but after running for a 20ish seconds there is starting to become a delay on the timer... :s (see code below)
now my question is is there a timer class implemented in the java library that is more accurate then the java swing timer?
if so could you guys tell me wich? :o
this was the output of the program:
chaning print for 162 time at 1346351773766
chaning print for 163 time at 1346351774766
chaning print for 164 time at 1346351775780
chaning print for 165 time at 1346351776779
chaning print for 166 time at 1346351777793
chaning print for 167 time at 1346351778792
chaning print for 168 time at 1346351779806
chaning print for 169 time at 1346351780806
Code:
package gui;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.Timer;
import domein.DomeinController;
public class MainFrame extends JFrame{
private static final long serialVersionUID = -8026416994513756565L;
private DomeinController domCntrl;
private Timer timer;
private int calcVisual;
public MainFrame(DomeinController domCntrl){
this.domCntrl = domCntrl;
this.setTitle("StartFrame");
this.setSize(800, 500);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
init();
}
private void init(){
timer = new Timer(999, new ActionListener(){
public void actionPerformed(ActionEvent e) {
calcVisual++;
repaint();
}
});
timer.start();
}
public void paint(Graphics g){
super.paintComponents(g);
System.out.printf("chaning print for %d time at %d\n", calcVisual, System.currentTimeMillis());
g.drawLine(10, 250, 790, 250);
if(calcVisual % 2 == 0){
paintCircles(g);
}else{
paintRectangles(g);
}
}
private void paintRectangles(Graphics g){
g.setColor(Color.red);
g.drawRect(375, 225, 50, 50);
g.setColor(Color.blue);
g.drawRect(350 , 200, 100, 100);
g.setColor(Color.green);
g.drawRect(325 , 175, 150, 150);
g.setColor(Color.CYAN);
g.drawRect(300 , 150, 200, 200);
g.setColor(Color.MAGENTA);
g.drawRect(275 , 125, 250, 250);
g.setColor(Color.orange);
g.drawRect(250 , 100, 300, 300);
g.setColor(Color.YELLOW);
}
private void paintCircles(Graphics g){
g.setColor(Color.red);
g.drawOval(350 , 200, 100, 100);
g.setColor(Color.blue);
g.drawOval(340 , 190, 120, 120);
g.setColor(Color.green);
g.drawOval(330 , 180, 140, 140);
g.setColor(Color.CYAN);
g.drawOval(320 , 170, 160, 160);
g.setColor(Color.MAGENTA);
g.drawOval(310 , 160, 180, 180);
g.setColor(Color.orange);
g.drawOval(300 , 150, 200, 200);
g.setColor(Color.YELLOW);
}
}
Re: java swing timer not precise enough?
You can use a Swing Timer for a simple game loop, but I'd change the state of the game based on changes in the system clock. For instance if I were trying to animate the movement of something, I'd use the delta-time from the clock in msecs to calculate the change in distance based on the velocity of the item. This can all be done within the Swing Timer.
Re: java swing timer not precise enough?
Your printing is done in the repainting process and so will include imprecision over and above what is inherent in the hardware and Timer software. Every 999ms you put an event into the queue: but the painting occurs when that event is subsequently processed. There may be lots of other things in the queue that get done first, or there may be nothing.
So using the delta time from some arbitrary starting point will tell you when the printing is being done. Alternatively ActionEvent does have a getWhen() method that tells you about the time of the event (I've never used it.)
As far as I know Windows has a "granularity" of 1000ms/64 == 16ms. So the computer may be keeping wonderful time, but at any instant it only tells you that time with a precision of 16ms. I mention that because your differences from 999ms are neatly within that range. You don't say, but if you're using Windows it might be fun to run the same program on a real OS and see what the outcome is.