Java 将repaint()与Thread.Sleep()相结合
我想做的很简单,我想在屏幕上展示一个算法的步骤,因此为什么我要尝试将repaint()与sleep()结合起来,但我做得不对,如果有人对它有足够的了解,首先解释一下这段代码的错在哪里,其次,我该怎么做才能让它工作 谢谢 在Summey中,这段代码要做的是绘制10个红色顶点,然后以200毫秒的间隔逐个消除它们 代码如下:Java 将repaint()与Thread.Sleep()相结合,java,swing,repaint,thread-sleep,Java,Swing,Repaint,Thread Sleep,我想做的很简单,我想在屏幕上展示一个算法的步骤,因此为什么我要尝试将repaint()与sleep()结合起来,但我做得不对,如果有人对它有足够的了解,首先解释一下这段代码的错在哪里,其次,我该怎么做才能让它工作 谢谢 在Summey中,这段代码要做的是绘制10个红色顶点,然后以200毫秒的间隔逐个消除它们 代码如下: public class Tester { public static void main(String[] args) { SwingU
public class Tester {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
ShowGUIGraph();
}
});
}
private static void ShowGUIGraph() {
JFrame f = new JFrame("something");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p=new JPanel();
p.setLayout(new BorderLayout());
p.add(BorderLayout.CENTER,new SomePanel());
f.add(p);
f.setPreferredSize(new Dimension(800,600));
f.pack();
f.setVisible(true);
}
}
public class SomePanel extends JPanel {
private static final long serialVersionUID = 1L;
LinkedList<Vertex> vertices=new LinkedList<Vertex>();
public SomePanel () {
for (int i=0;i<10;i++) {
Vertex v=new Vertex(i);
v.setLocation(20+30*i, 20+30*i);
vertices.add(v);
}
traverseVerticesRecoursive(0);
traverseVerticesNonRecoursive();
}
public void traverseVerticesRecoursive(int i) {
if (i>=vertices.size()) return;
vertices.get(i).setColor(Color.black);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
repaint();
traverseVerticesRecoursive(i+1);
}
public void traverseVerticesNonRecoursive() {
for (int i=0;i<10;i++) {
vertices.get(i).setColor(Color.red);
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
repaint();
}
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
for (int i=0;i<vertices.size();i++) {
vertices.get(i).paintVertex(g);
}
}
}
public class Vertex {
private int x,y,tag,r=20;
private Color color=Color.red;
Vertex (int i) {
tag=i;
}
public void setLocation(int x0,int y0) {
x=x0;
y=y0;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public void setColor(Color c) {
color=c;
}
public boolean colorIs(Color c) {
return (color.equals(c));
}
public void paintVertex(Graphics g) {
g.setColor(color);
g.fillOval(x,y,r,r);
g.setColor(Color.BLACK);
g.drawOval(x,y,r,r);
g.drawString(""+tag, x+r/2, y+r/2+4);
}
public int getR() {
return r;
}
}
公共类测试器{
公共静态void main(字符串[]args){
SwingUtilities.invokeLater(新的Runnable(){
公开募捐{
ShowGUIGraph();
}
});
}
私有静态void ShowGUIGraph(){
JFrame f=新的JFrame(“某物”);
f、 setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel p=新的JPanel();
p、 setLayout(新的BorderLayout());
p、 添加(BorderLayout.CENTER,newsomepanel());
f、 加(p);
f、 设置首选尺寸(新尺寸(800600));
f、 包装();
f、 setVisible(真);
}
}
公共类SomePanel扩展了JPanel{
私有静态最终长serialVersionUID=1L;
LinkedList顶点=新建LinkedList();
公共事务委员会(){
for(int i=0;i=vertices.size())返回;
顶点.get(i).setColor(Color.black);
试一试{
睡眠(200);
}捕捉(中断异常e){
//TODO自动生成的捕捉块
e、 printStackTrace();
}
重新油漆();
横切反射(i+1);
}
public void TraverseVertices非递归(){
对于(int i=0;i不在事件调度线程中休眠;这将导致GUI冻结。对于动画,请使用EDT友好的实用程序类,例如。不要在事件调度线程中休眠;这将导致GUI冻结。对于动画,请使用EDT友好的实用程序类,例如。只是一些可能使代码干净的想法呃,
在SomePanel
类中,将遍历代码放入构造函数外的方法中。构造函数用于初始化字段
首先启动静态GUI,然后生成一个工作线程,通过前面的方法进行更新(这将是您的小型“引擎”)。在此线程中,您可以调用sleep
在traverseverticserecoursive
方法中,仅在UI线程上重新绘制,并在工作线程上更新状态
您应该做的主要修改是,不要像他们在第一个答案中告诉您的那样,用睡眠调用阻止GUI线程。只是一些可能使代码更干净的想法:
在SomePanel
类中,将遍历代码放入构造函数外的方法中。构造函数用于初始化字段
首先启动静态GUI,然后生成一个工作线程,通过前面的方法进行更新(这将是您的小型“引擎”)。在此线程中,您可以调用sleep
在traverseverticserecoursive
方法中,仅在UI线程上重新绘制,并在工作线程上更新状态
您应该做的主要修改是,不要像他们在第一个答案中告诉您的那样,用睡眠调用阻止GUI线程。线程。睡眠是一个长时间运行的任务。当您在EDT中运行这样一个任务时,它会阻止所有重绘请求的执行。所有挂起的重绘请求以及在e睡眠阶段排队等待将来处理
因此,当EDT退出睡眠
阶段时,它会合并所有此类重新绘制请求(如果启用了合并,这是默认属性)如果未启用合并,则所有排队请求都将连续执行,其间没有任何时间间隔。因此,UI似乎没有更新
要纠正这种情况,请使用在特定时间间隔后定期触发的计时器。线程。睡眠是一项长时间运行的任务。当您在EDT中运行这样的任务时,它会阻止所有重新绘制请求的执行。所有挂起且在睡眠阶段发送的重新绘制请求都会被禁用e排队等待将来处理
因此,当EDT退出睡眠
阶段时,它会合并所有此类重新绘制请求(如果启用了合并,这是默认属性)如果未启用合并,则所有排队请求都将连续执行,其间没有任何时间间隔。因此,UI似乎没有更新
要纠正这种情况,请使用一个在特定时间间隔后定期触发的计时器。Guy,您可以使用一个与EDT线程不同的新线程来制作动画。例如
void play() {
Thread thread = new Thread() {
@Override
public void run() {
game();
}
};
thread.start();
}
void game() {
for (; ; ) {
switch (state) {
case GameData.ANIMATING:
// call some function as repaint() to update GUI
break;
case GameData.GAME_ENDED:
return;
default:
break;
}
diffTime = System.currentTimeMillis() - beforeTime;
sleepTime = delay - diffTime;
sleepTime = (sleepTime < 0) ? 0 : sleepTime;
Thread.sleep(sleepTime);
}
}
void play(){
线程线程=新线程(){
@凌驾
公开募捐{
游戏();
}
};
thread.start();
}
无效游戏(){
对于(;;){
开关(状态){
case GameData.ANIMATING:
//将某些函数调用为repaint()以更新GUI
打破
案例GameData.GAME_结束:
返回;
违约:
打破
}
diffTime=System.currentTimeMillis()-beforeTime;
睡眠时间=延迟-扩散时间;
睡眠时间=(睡眠时间<0)?0:睡眠时间;
睡眠(睡眠时间);
}
}
伙计,你可以使用一个与EDT线程不同的新线程来制作动画。例如
void play() {
Thread thread = new Thread() {
@Override
public void run() {
game();
}
};
thread.start();
}
void game() {
for (; ; ) {
switch (state) {
case GameData.ANIMATING:
// call some function as repaint() to update GUI
break;
case GameData.GAME_ENDED:
return;
default:
break;
}
diffTime = System.currentTimeMillis() - beforeTime;
sleepTime = delay - diffTime;
sleepTime = (sleepTime < 0) ? 0 : sleepTime;
Thread.sleep(sleepTime);
}
}
void play(){
线程线程=新线程(){
@凌驾
公开募捐{
游戏();
}
};
thread.start();
}
无效的