将 repaint() 与 Thread.Sleep() 结合起来
我想做的事情非常简单,我想在屏幕上显示算法的步骤,因此为什么我尝试将 repaint() 与 sleep() 结合起来,但我做错了,如果有人足够了解,我会喜欢它首先解释一下这段代码有什么问题,其次,我该怎么做才能让它工作......
谢谢!
在夏天,这段代码的目的是绘制 10 个红色顶点,然后以 200 毫秒的间隔将它们一一涂黑。
这是代码:
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;
}
}
What im trying to do is pretty simple, I want to show the steps of an algorithm on the screen, hence why im trying to combine repaint() with sleep(), but I am doing it wrong, Id love it if someone knows enough about it to firstly explain whats wrong with this code, and secondly, what do i do to make it work...
thanks!
in summery, what this code was meant to do is paint 10 red vertices, then balcken em one by one in intervals of 200 milliseconds.
here's the code:
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;
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
不要在事件派发线程中休眠;这将导致 GUI 冻结。对于动画,请使用 EDT 友好的实用程序类,例如
javax.swing.Timer
。Do not sleep in the Event Dispatch Thread; this will cause the GUI to freeze. For animation, use an EDT-friendly utility class, such as
javax.swing.Timer
.一些可能使您的代码更简洁的想法:
SomePanel
类中,将遍历代码放在构造函数之外的方法中。构造函数用于初始化字段。sleep
。traverseVerticesRecoursive
方法中,仅在 UI 线程上进行重绘,并在工作线程上进行状态更新。您应该做的主要修改是不要通过睡眠调用来阻止 GUI 线程,正如他们在第一个答案中告诉您的那样。
Just a few ideas that might make your code cleaner:
SomePanel
class, put the traversing code in a method out of the constructor. Constructors are intended for initializing fields.sleep
.traverseVerticesRecoursive
method, do only the repaint on the UI thread, and the status update on your worker thread.Tha main modification you should do is not to block the GUI thread with sleep calls, as they have told you in the first answer.
Thread.sleep
是一个长时间运行的任务。当您在 EDT 中运行此类任务时,它会阻止执行所有重绘请求。所有待处理的重绘请求和在睡眠阶段发送的重绘请求都会排队等待将来处理。因此,当 EDT 退出睡眠阶段时,它会将所有此类重绘请求(如果启用了默认属性的合并)合并为一个要执行的重绘。如果未启用合并,则所有排队的请求都会串行执行,中间没有任何时间间隔。结果似乎 UI 没有更新。
要纠正这种情况,请使用
计时器
,该计时器会在特定时间间隔后定期触发。Thread.sleep
is a long running task. When you a running such a task in the EDT it blocks all repaint requests from being executed. All repaint requests which are pending and which were sent during the sleep phase are queued for future processing.As a result when the EDT comes out of the
sleep
phase it coalesce all such repaint request (if coalescing is enabled which is the default property) into a single repaint which gets executed. If coalescing is not enabled then all queued request are executed serially without any time gap in between. As a result it seems that the UI did not update.To correct the situation use a
timer
which triggers periodically after specific intervals of time.伙计,你可以使用与 EDT 线程不同的新线程来制作动画。例如,
Guy, you could use a new Thread differ with EDT thread to make an animation. For example,