[英]Thread.sleep() doesn't strike when expected
我想知道为什么Thread.sleep()
没有在预期的时间点出现。
我期望绘制第一个矩形,暂停2秒,然后是第二个矩形的外观。 然而,暂停首先开始,然后两个矩形被“一次”绘制。
为什么会出现这种情况?
提前感谢任何建议。
public class Figure extends JPanel
{
Point a = new Point(10, 10);
Point b = new Point(110, 10);
Point c = new Point(110, 110);
Point d = new Point(10, 110);
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
g.drawLine(a.x, a.y, b.x, b.y);
g.drawLine(b.x, b.y, c.x, c.y);
g.drawLine(c.x, c.y, d.x, d.y);
g.drawLine(d.x, d.y, a.x, a.y);
try
{
Thread.sleep(2000);
}
catch(InterruptedException ex)
{
}
Point newA = rotate(a, 45);
Point newB = rotate(b, 45);
Point newC = rotate(c, 45);
Point newD = rotate(d, 45);
g.drawLine(newA.x, newA.y, newB.x, newB.y);
g.drawLine(newB.x, newB.y, newC.x, newC.y);
g.drawLine(newC.x, newC.y, newD.x, newD.y);
g.drawLine(newD.x, newD.y, newA.x, newA.y);
}
private Point rotate(Point p, int degree)
{
//to shift the resulting Point some levels lower
int offset = 100;
int x = (int)(Math.cos(degree) * p.x + Math.sin(degree) * p.y);
int y = (int)(-Math.sin(degree) * p.x + Math.cos(degree) * p.y) + offset;
Point ret = new Point(x, y);
return ret;
}
}
这是因为您没有进入Swings事件循环; 只有这样才能保证执行paint命令。 此外,这也是为什么永远不要在事件循环线程中睡觉的一个原因...
我将第二个矩形的代码更改为
try
{
Thread.sleep(2000);
}
catch(InterruptedException ex)
{
}
a = rotate(a, 45);
b = rotate(b, 45);
c = rotate(c, 45);
d = rotate(d, 45);
g.drawLine(a.x, a.y, b.x, b.y);
g.drawLine(b.x, b.y, c.x, c.y);
g.drawLine(c.x, c.y, d.x, d.y);
g.drawLine(d.x, d.y, a.x, a.y);
方法paintComponent似乎是通过pereptually运行的:现在一个矩形旋转,它的前身消失等等......
调用所有这些绘制方法并没有物理绘制任何东西,它只是将绘图命令放入图形管道中,而你所有的sleep()正在做的是阻止管道的处理。 你应该做的是切换一个变量,该变量告诉方法绘制哪些位,并以所需的间隔从一个单独的线程向外部触发repaint()。
永远不要在AWT事件线程中使用Thread.sleep()(例如paintComponent()或各种onclick处理程序,它们总是在AWT事件线程中运行) - 阻止所有事件被处理 - 键,鼠标等,你的应用程序将看起来像是冻结了。 一个快速而肮脏的解决方案:
private boolean isRotating = false;
@Override
protected void paintComponent(Graphics g)
{
super.paintComponent(g);
if (!isRotating) {
g.drawLine(a.x, a.y, b.x, b.y);
g.drawLine(b.x, b.y, c.x, c.y);
g.drawLine(c.x, c.y, d.x, d.y);
g.drawLine(d.x, d.y, a.x, a.y);
isRotating = true;
Utils.swingInvokeDelayed(new Runnable() { public void run(){ repaint();}}, 2000);
} else {
Point newA = rotate(a, 45);
Point newB = rotate(b, 45);
Point newC = rotate(c, 45);
Point newD = rotate(d, 45);
g.drawLine(newA.x, newA.y, newB.x, newB.y);
g.drawLine(newB.x, newB.y, newC.x, newC.y);
g.drawLine(newC.x, newC.y, newD.x, newD.y);
g.drawLine(newD.x, newD.y, newA.x, newA.y);
isRotating = false;
}
}
public class Utils {
// ideal is to keep 0 as corePoolSize, but then the executor simply does not work :(
private static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(1, newDaemonThreadFactory(Utils.class.getSimpleName()));
private static ThreadFactory newDaemonThreadFactory(final String threadName) {
return new ThreadFactory() {
public Thread newThread(Runnable r) {
final Thread result = new Thread(r, threadName);
result.setDaemon(true);
return result;
}
};
}
public static void swingInvokeDelayed(final Runnable r, final long delay) {
executor.schedule(new Runnable() {
public void run() {
SwingUtilities.invokeLater(r);
}
}, delay, TimeUnit.MILLISECONDS);
}
}
Swingworker就是你要找的
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.