For what I understand Swing will decide when things need to be repainted, that would explain why paintComponent()
is executing twice. But I've made an application that sleeps 16ms, repaints, sleeps 16 ms, repaints, sleeps 16 ms, and so on:
while(true)
{
frame.repaint();
try{Thread.sleep(16)}catch(Exception e){}
}
It should work at 60fps. However, FPS measuring programs (like FRAPS) show the application runs at 120fps. So basically, what the application is doing is: draw frame, draw frame, sleep, draw frame, draw frame, sleep... How can I tell swing to draw one frame for each repaint()
call? (Oh and I've tried using a Timer
instead of sleep()
, and the result is the same).
Here's for example the SwingPaintDemo found at an Oracle tutorial. I've added a while loop that will repaint every 16ms. I've also set undecorated to true (it's the only way FRAPS will show me the actual number of frames per second).
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/*
***************************************************************
* Silly Sample program which demonstrates the basic paint
* mechanism for Swing components.
***************************************************************
*/
public class SwingPaintDemo {
public static void main(String[] args) {
JFrame f = new JFrame("Aim For the Center");
f.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System.exit(0);
}
});
Container panel = new BullsEyePanel();
panel.add(new JLabel("BullsEye!", SwingConstants.CENTER), BorderLayout.CENTER);
f.setUndecorated(true);
f.setSize(200, 200);
f.getContentPane().add(panel, BorderLayout.CENTER);
f.show();
while(true)
{
f.repaint();
try{Thread.sleep(16);}catch(Exception e){}
}
}
}
/**
* A Swing container that renders a bullseye background
* where the area around the bullseye is transparent.
*/
class BullsEyePanel extends JPanel {
public BullsEyePanel() {
super();
setOpaque(false); // we don't paint all our bits
setLayout(new BorderLayout());
setBorder(BorderFactory.createLineBorder(Color.black));
}
public Dimension getPreferredSize() {
// Figure out what the layout manager needs and
// then add 100 to the largest of the dimensions
// in order to enforce a 'round' bullseye
Dimension layoutSize = super.getPreferredSize();
int max = Math.max(layoutSize.width,layoutSize.height);
return new Dimension(max+100,max+100);
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Dimension size = getSize();
int x = 0;
int y = 0;
int i = 0;
while(x < size.width && y < size.height) {
g.setColor(i%2==0? Color.red : Color.white);
g.fillOval(x,y,size.width-(2*x),size.height-(2*y));
x+=10; y+=10; i++;
}
}
}