4

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...

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
daGrevis
  • 21,014
  • 37
  • 100
  • 139

4 Answers4

7

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();
         }
      });
   }
}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
1

I think Graphics.clearRect is what you're looking for.

corlettk
  • 13,288
  • 7
  • 38
  • 52
  • 2
    Keith you putz! This isn't a JComponent but a JPanel. Nah, it's the super method, and needs to be in paintComponent. Hope all is going well with you and yours. Regards, Pete – Hovercraft Full Of Eels Apr 30 '11 at 14:31
  • @Hovercraft Full Of Eels: I agree with that. However, it's a good practice to do `clearRect` in the first steps to **understand** how things work. – Alba Mendez Apr 30 '11 at 14:45
  • 1
    @jmendeth: I'm not sure. It is needed when doing graphics in a JComponent, but a JPanel will do this for you if you call the super method, and so I think it is best to use the proper tool for the situation. But I was also just giving Keith a hard time since I haven't seen him in ages (from my old Sun forum days). – Hovercraft Full Of Eels Apr 30 '11 at 14:47
  • @HFOE: Hi!!! Long time no see! Strangely enough, I really really want one of [these](http://www.thinkgeek.com/homeoffice/lights/e854/?cpg=wnrss). And yes I'm STILL a putz, and still need to learn to actually READ the questions (carefully)... In my defence: AWT is pure filth! (IMHO), and I bought me one of [these](http://en.wikipedia.org/wiki/FPV_F6) (a BF MkII)... Her name is Betty, she's black, and she BITES! – corlettk May 01 '11 at 00:49
  • Cool! Myself I'd like to get an Aston Martin DB6 Volante like Prince William, but my wife Diane says it's either the car or her. I'm going to sure miss Diane. – Hovercraft Full Of Eels May 04 '11 at 17:00
1

I would do it like this:

public void paintComponent(Graphics g)
{
   super.paintComponent(g);
   //draw all the other stuff
}
james_bond
  • 6,778
  • 3
  • 28
  • 34
1

Aaah! This is normal. Imagine your panel as a blackboard. Each time you want to repaint what you have writed in, you will have to erase the blackboard first.

In Java, as well as in Graphics in general, things go in a similar way. In your paint method, do this:

Graphics.clearRect(0,0, getWidth(),getHeight());
        //CLEAR the entire component first.

Graphics.drawString(...); //now that the panel is blank, draw the string.

When you can handle the topic better, do super.paint(Graphics) instead of clearRect().

Alba Mendez
  • 4,432
  • 1
  • 39
  • 55