I never worked with Timer
s before so my problem is probably stupid one really. My program draws a circle which is red and after random seconds the circle should change its color to green. I just made a swing timer as you can see below in the code. And it enters actionPerformed()
method but it doesn't change color. Could you help me somehow fix my problem with changing colors?
My code:
package igrica;
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 implements ActionListener{
JFrame frame;
Timer timer;
Random r;
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 {
public void paintComponent(Graphics g) {
g.setColor(Color.red);
g.fillOval(100, 100, 100, 100);
Random r = new Random();
Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.out.println("Timer out");
g.setColor(Color.green);
g.fillOval(100, 100, 100, 100);
}
});
timer.start();
}
}
}
Setting up a timer involves the following: Creating a timer object. Registering one or more ActionListener on it to be notified when the timer “goes off” where the actionPerformed(ActionEvent e) method in this listener should contain the code for whatever task you need to be performed.
repaint(): This method tells Swing that an area of the window is dirty. revalidate(): This method tells the layout manager to recalculate the layout that is necessary when adding components.
A Swing timer (an instance of javax. swing. Timer ) fires one or more action events after a specified delay. Do not confuse Swing timers with the general-purpose timer facility in the java.
There's quite the mess in your code. Try this:
public class ChangingCircle {
Color color = Color.RED;
MyPanel panel = new MyPanel();
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
ChangingCircle gui = new ChangingCircle();
gui.go();
});
}
public void go() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(panel, BorderLayout.CENTER);
frame.pack();
frame.setVisible(true);
Random r = new Random();
Timer timer = new Timer(r.nextInt(5000) + 1000, new ActionListener() {
public void actionPerformed(ActionEvent ev) {
System.out.println("Timer");
color = Color.GREEN;
panel.repaint();
}
});
timer.setRepeats(false);
timer.start();
}
class MyPanel extends JPanel {
private int size = 100, loc = 100;
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(color);
g.fillOval(loc, loc, size, size);
}
@Override
public Dimension getPreferredSize() {
return new Dimension(size + loc, size + loc);
}
}
}
The idea is that the timer only changes the property of the shape to be drawn and then calls repaint()
to reflect the change. The paintComponent
is called whenever it is needed, even in quick succession and should return quickly.
Specific Notes:
paintComponent
since it is called many times and that will create and start many timers.super.paintComponent(g);
as the first thing inside paintComponent
.ActionListener
that does nothing.General tips:
@Override
annotation when applicable.pack()
on the frame instead of setting its size manually and @Override
the getPreferredSize
method of the component you paint on. Return a meaningful size based on what you draw.add(component, location)
and not the other way around (deprecated).Random r
for example).Color.RED
instead of Color.red
).If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With