簡短的回答
您可以使用Thread.sleep
但不能從paint方法。從外面使用它,只需重新打開面板。
龍答案
因爲它是現在,你的代碼繪製的面板,直至暫停是完成它返回。從視覺上看,油漆需要花費太多時間才能完成。
你需要什麼,是有一個「型號」畫。你的組件只會繪製該模型並完成。
然後,您每秒鐘都會向模型中添加更多「事物」,就是這樣。
例如,比方說,你的模式是線組成的數組:
class Line {
int x1, y1, x2, y2;
}
class LineJPanel extends JPanel {
// this is the private model
private Line[] lines = new Line[10];
.....
您需要在paint方法做的是畫那些線:
// 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);
}
}
}
就是這樣。這樣你就不會凍結GUI。
要添加具有越來越多行的效果,您將創建一個單獨的線程並向其中添加行。
爲了簡單起見,你可以添加線程在構造函數中:
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();
}
這應該增加更多線路到「模式」(陣列)一樣簡單,讓組件重新油漆他們。
左右的時間完成,我們可以添加,創建一個線addRandomLine
方法,設置一些隨機值,並把它在陣列中的代碼:
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;
}
}
所以,結束了你的新的線程將如下所示:
Thread t = new Thread(){
public void run(){
while(true){
addRandomLine();
repaint();
// and as per the requiement:
try{
Thread.sleep(1000);
}catch(InterruptedException ie){}
}
}
};
請注意,這將在其他線程中調用repaint
與EDT不同。爲了解決這個問題,我們將使用:SwingUtilities.invokeLater
這讓我們定義一個方法被調用「最終」在EDT:
所以,最終的代碼(從我的一部分某些格式的改進)將是:
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;
}
}
}
結果是一個非常好的 「行動畫」 面板:
like this http://img689.imageshack.us/img689/8414/capturadepantalla201006bk.png
只是去'javax.swing.Timer'。如果可能,避免多線程 - 這很難得到正確的結果。一些聲稱在Swing中是線程安全的方法不是。 – 2010-06-21 18:23:48