title: paintComponent paints twice
body: <p>For what I understand Swing will decide when things need to be repainted, that would explain why <code>paintComponent()</code> is executing twice. But I've made an application that sleeps 16ms, repaints, sleeps 16 ms, repaints, sleeps 16 ms, and so on:</p>
  
  <pre><code>while(true)
  {
      frame.repaint();
      try{Thread.sleep(16)}catch(Exception e){}
  }
  </code></pre>
  
  <p>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 <code>repaint()</code> call? (Oh and I've tried using a <code>Timer</code> instead of <code>sleep()</code>, and the result is the same).</p>
  
  <p>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).</p>
  
  <pre><code>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 &lt; size.width &amp;&amp; y &lt; 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++;
          }
      }
  }
  </code></pre>