Do not start the timer from the paintComponent method. This method should only be for drawing and drawing. Instead, start a timer in your constructor and within the TimerPerromed action and call repaint() , change the state of the class field and use this information in paintComponent to use this information to paint any new information.
eg.
import java.awt.BorderLayout; import java.awt.Color; import java.awt.Graphics; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.Random; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.Timer; public class ChangingCircle { JFrame frame; public static void main(String[] args) { ChangingCircle gui = new ChangingCircle(); gui.go(); } public void go() { frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); MyPanel panel = new MyPanel(); frame.getContentPane().add(BorderLayout.CENTER, panel); frame.setSize(300, 300); frame.setVisible(true); } public void actionPerformed(ActionEvent event) { frame.repaint(); } class MyPanel extends JPanel { private Random r = new Random(); private boolean draw = false; public MyPanel() { Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() { public void actionPerformed(ActionEvent ev) { draw = true; repaint(); } }); timer.setRepeats(false); timer.start(); } public void paintComponent(Graphics g) { super.paintComponent(g); if (draw) { g.setColor(Color.red); g.fillOval(100, 100, 100, 100); } } } }
Also, be sure to call the super paintComponent method from your override.
If you need to change colors, give the JPanel the Color field, say, called color and change its value from the timer, and then call repaint() . Again in paintComponent, use the value of this field to draw an oval. Also in this situation, the timer should be repeated, so get rid of timer.setRepeats(false) in this situation.
source share