Graphics.drawString() Draws Over My Old String

daGrevis picture daGrevis · Apr 30, 2011 · Viewed 16k times · Source

I'm working on simple counter. My problem is that drawString() method draws new string over the old one. How to clear the old one before? Code...

package foobar;

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;

public class board extends JPanel implements Runnable {

    Thread animator;
    int count;

    public board() {
        this.setBackground( Color.WHITE );
        count = 0;
        animator = new Thread( this );
        animator.start();
    }

    @Override
    public void run() {
        while( true ) {
            ++count;
            repaint();
            try {
                animator.sleep( 1000 );
            } catch ( InterruptedException e ) {}
        }
    }

    @Override
    public void paint( Graphics Graphics ) {
        Graphics.drawString( Integer.toString( count ), 10, 10 );
    }
}

P.S. I'm new to Java, so please don't be afraid to tell me what other things I should fix in my code...

Answer

Hovercraft Full Of Eels picture Hovercraft Full Of Eels · Apr 30, 2011

Several problems in your code:

  • Don't have a while (true) loop or Thread.sleep in a Swing GUI. Use a Swing Timer instead.
  • Override JPanel's paintComponent, not its paint method.
  • The first call in paintComponent(Graphics g) should be super.paintComponent(g), so your JPanel can do its house keeping and get rid of old graphics.

edit:

  • My bad, your while (true) and Thread.sleep(...) will work since they're in a background thread, but,...
  • Thread.sleep is a static method and should be called on the class, Thread, and
  • I still think a Swing Timer would be an easier way to do this.
  • Even easier still is to not even use a paint or paintComponent method, but rather simply set the text of a JLabel for your display.

e.g.,

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.*;

public class Board2 extends JPanel {
   private static final int TIMER_DELAY = 1000;

   private int counter = 0;
   private JLabel timerLabel = new JLabel("000");

   public Board2() {
      add(timerLabel);
      new Timer(TIMER_DELAY, new ActionListener() {
         @Override
         public void actionPerformed(ActionEvent e) {
            counter++;
            timerLabel.setText(String.format("%03d", counter));
         }
      }).start();
   }

   private static void createAndShowUI() {
      JFrame frame = new JFrame("Board2");
      frame.getContentPane().add(new Board2());
      frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      frame.pack();
      frame.setLocationRelativeTo(null);
      frame.setVisible(true);
   }

   public static void main(String[] args) {
      java.awt.EventQueue.invokeLater(new Runnable() {
         public void run() {
            createAndShowUI();
         }
      });
   }
}