Reputation: 69
I'm just trying to figure out how Threads work (i.e. I'm a beginner). This program does not serve any purpose other than this.
However, it does not work as intended. My goal was make a the Circle brighter and brighter so that it disappears in the background. But the repaint() call in the Thread does not seem to work.
Here is my code:
public class Run {
public static void main(String[] args) {
new Circle();
}
}
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
@SuppressWarnings("serial")
public class Circle extends JFrame implements Runnable {
private boolean running = false;
private Thread t;
Color currentColor;
int currentRed, currentGreen, currentBlue;
public Circle() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setPreferredSize(new Dimension(150,150));
start();
repaint();
pack();
setVisible(true);
}
@Override
public void paint(Graphics g) {
//super.paint(g);
//currentColor = g.getColor();
//currentRed = currentColor.getRed();
//currentGreen = currentColor.getGreen();
//currentBlue = currentColor.getBlue();
g.setColor(new Color(currentRed++,currentGreen++,currentBlue++));
g.fillOval(7,30,100,100);
}
public synchronized void stop() {
running = false;
t.interrupt();
}
public synchronized void start() {
System.out.println("start");
if (!running) {
running = true;
t = new Thread(this);
t.start();
}
}
@Override
public void run() {
while(running) {
try {
Thread.sleep(5);
System.out.println("run");
repaint();
System.out.println("repaint");
} catch(InterruptedException e) {
}
}
}
}
I also tried to call paint() instead, but I'm aware that I shouldn't do this and it didn't work anyways. It kind of makes sense to me. But it is unclear to me, why repaint doen't work...
Upvotes: 0
Views: 1343
Reputation: 18812
The following is a working version of your code. Note the comments:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.SwingUtilities;
public class Circle extends JFrame implements Runnable {
private boolean running = false;
private Thread t;
int currentRed = 0, currentGreen = 0, currentBlue = 0;
public Circle() {
setDefaultCloseOperation(EXIT_ON_CLOSE);
setPreferredSize(new Dimension(150,150));
//repaint(); //not really needed here
pack();
setVisible(true);
start();
}
@Override
public void paint(Graphics g) {
g.setColor(new Color(currentRed,currentGreen,currentBlue));
g.fillOval(7,30,100,100);
//modify color and make sure it is valid
currentRed = ++currentRed % 256;
currentGreen = ++currentGreen % 256; //Equivalent to: currentGreen = currentGreen == 255 ? 0 : currentGreen+1;
currentBlue = ++currentBlue % 256;
}
public synchronized void stop() {
running = false;
t.interrupt();
}
public synchronized void start() {
if (!running) {
running = true;
t = new Thread(this);
t.start();
}
}
@Override
public void run() {
while(running) {
try {
Thread.sleep(5);
repaint();
} catch(InterruptedException e) { //do not mute exceptions
e.printStackTrace();
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new Circle());
}
}
A better implementation incorporating many of the tips you got in comments would be:
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
public class Circle extends JPanel { //do custom painting on a JPanel
private boolean running = false;
private int currentRed = 0, currentGreen = 0, currentBlue = 0;
private final Timer timer; //use swing tools to update gui
private static final int DELAY = 5, W = 100, H = 100, OFFSET = 25;
public Circle() {
timer = new Timer(DELAY, e -> repaint());
setPreferredSize(new Dimension(W + 2*OFFSET,H + 2*OFFSET));
}
public static void createAndShowGui(){
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Circle circle = new Circle();
frame.add(circle);
frame.pack();
frame.setVisible(true);
circle.start();
}
@Override
public void paintComponent(Graphics g) { //for custom painting override paintComponent
super.paintComponent(g); //always call super
g.setColor(new Color(currentRed,currentGreen,currentBlue));
g.fillOval(OFFSET,OFFSET,W,H);
//modify color and make sure it is valid
currentRed = ++currentRed % 256;
currentGreen = ++currentGreen % 256;
currentBlue = ++currentBlue % 256;
}
public void stop() {
running = false;
timer.stop();
}
public void start() {
if (!running) {
running = true;
timer.start();
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Upvotes: 2