Short answer
You can use Thread.sleep
but not from the paint method. Use it from outside and just reapaint your panel.
Long answer
As it is now, your code paints the panel, and until the pause is finish it returns. Visually it would look like the paint took too much time to finish.
What you need, is to have a "model" to paint. Your component would just paint that model and finish.
Then you add more "things" to your model every second, and that's it.
For instance. Let's say your model is an array of lines:
class Line {
int x1, y1, x2, y2;
}
class LineJPanel extends JPanel {
// this is the private model
private Line[] lines = new Line[10];
.....
What you need to do in your paint method is to draw those lines:
// exactly as you have them:
@Override
public void paint(Graphics g) {
super.paint(g);
drawRandomLines(g);
}
// Changed. Do no "sleep" here, or you'll freeze the GUI
// just draw whatever your model is/has.
private void drawRandomLines(Graphics g) {
for( Line line : lines ){
if( line != null ){
g.drawLine( line.x1, line.y1, line.x2, line.y2 );
}
}
}
And that's it. That way you won't freeze the GUI.
To add the effect of having more and more lines, you'll create a separate thread and add lines to it.
To keep things simple, you can add that thread in the constructor:
public LineJPanel() {
setSize(500,500);
Thread t = new Thread(){
public void run(){
while( true ) {
// add random lines and repaint
// sleep for a while
// and repeat.
}
}
};
t.start();
}
That should as simple as adding more lines into the "model" ( the array ) and let the component re-paint them.
So to complete the code we could add a addRandomLine
method that creates a line, set some random values, and put it in the array:
private void addRandomLine(){
Line line = new Line();
line.x1 = random.nextInt(500);
line.y1 = random.nextInt(500);
line.x2 = random.nextInt(500);
line.y2 = random.nextInt(500);
lines[count++] = line;//put it in the next position
// if we reach the limit, start all over again
// from 0
if( count == lines.length ){
count = 0;
}
}
So, wrapping up your new thread would look like:
Thread t = new Thread(){
public void run(){
while( true ){
addRandomLine();
repaint();
// and as per the requiement:
try{
Thread.sleep( 1000 );
}catch( InterruptedException ie ){}
}
}
};
Be aware that, this would invoke repaint
in other thread different to the EDT. To fix this we would use: SwingUtilities.invokeLater
which let us define a method to be invoked "eventually" in the EDT:
So, the final code ( with some formatting enhancements from my part ) would be:
import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class Askisi2_3 extends JFrame {
public Askisi2_3() {
initialiseComponents();
}
private void initialiseComponents() {
JPanel panel = new LineJPanel();
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
add(panel);
setSize(500, 500);
setVisible(true);
}
public static void main( String [] args ) {
new Askisi2_3();
}
}
// line abstraction
class Line {
int x1, y1, x2, y2;
}
class LineJPanel extends JPanel {
// this is the private model
private Line[] lines = new Line[10];// fixed of size 10 by now.
// private internal index position
private int count = 0;
// generates "random" numbers
private Random random = new Random();
// create the panel and start adding more lines in a separate thread.
public LineJPanel() {
setSize(500,500);
Thread t = new Thread(){
public void run(){
// forever:
while( true ){
//add another line
addRandomLine();
// rapaint it
SwingUtilities.invokeLater( new Runnable(){
public void run(){
repaint();
}
});
// sleep for while
try{
Thread.sleep( 1000 );
}catch( InterruptedException ie ){}
}
}
};
t.start();
}
// just draw the model
private void drawRandomLines(Graphics g) {
for( Line line : lines ){
if( line != null ){
g.drawLine( line.x1, line.y1, line.x2, line.y2 );
}
}
}
@Override
public void paint(Graphics g) {
super.paint(g);
drawRandomLines(g);
}
// add another line to the "model"
private void addRandomLine(){
Line line = new Line();
line.x1 = random.nextInt(500);
line.y1 = random.nextInt(500);
line.x2 = random.nextInt(500);
line.y2 = random.nextInt(500);
lines[count++] = line;
if( count == lines.length ){
count = 0;
}
}
}
The result is a very nice "line animated" panel: