I am trying out a program with Java Swing that draws Random Lines on a JPanel
. For this I have overridden the paintComponent(Graphics g)
method of the JPanel.
I'm also using a Thread to continuously repaint the component with a fixed delay between repaints.
The thread is being controlled by a JButton
that can start and stop the painting of the component.
The whole panel is then embedded in a JFrame
and shown on screen.
When I execute the code and Start the painting, I see that the "Start" Button is "bleeding" on to the JPanel
where I'm painting the random lines.
Can anyone explain me why this is happening?
Here's an executable Java code for recreating the issue. I'm also adding screenshots for more clarity.
package application;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class RandomLines extends JPanel implements Runnable{
private static final long serialVersionUID = 3312914356515718206L;
private boolean running = false;
private boolean init = false;
private Point startPoint = getRandomPoint();
private Point endPoint = getRandomPoint();
public RandomLines() {
setBounds(0, 0, 400, 400);
setPreferredSize(new Dimension(400, 400));
}
@Override
public synchronized void paintComponent(Graphics g) {
if(init == false) {
g.setColor(Color.cyan);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.black);
init = true;
}
g.drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y);
}
public void run() {
while(running) {
repaint();
delay();
startPoint = endPoint;
endPoint = getRandomPoint();
}
}
private void delay() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
private Point getRandomPoint() {
int w = getWidth();
int h = getHeight();
int randX = (int) (Math.random() * 10000 % w);
int randY = (int) (Math.random() * 10000 % h);
return new Point(randX, randY);
}
public void createAndShowGui() {
JFrame frame = new JFrame("Random Lines");
frame.setSize(400, 400);
frame.add(this);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton b = new JButton("Start");
b.addActionListener(al -> {
if (running == false) {
frame.setVisible(true);
running = true;
b.setText("Stop");
Thread t = new Thread(RandomLines.this);
t.start();
} else {
frame.setVisible(false);
frame.dispose();
running = false;
b.setText("Start");
}
});
JOptionPane.showOptionDialog(null, b, "Control Random Lines", JOptionPane.OK_OPTION, JOptionPane.PLAIN_MESSAGE, null, new String[]{"Close"}, null);
}
public static void main(String[] args) {
RandomLines rl = new RandomLines();
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run() {
rl.createAndShowGui();
}
});
}
}
Here is a screen shot explaining the "bleeding" problem..
I hope I've detailed the question enough for others to understand. Let me know if you need more details.
Update
One observation I had was that when I use multiple monitors and have the JOptionPane and JFrame on two different monitors. The problem does not occur.
But why does it even happen in the first place?