簡體   English   中英

Thread.sleep()在預期時不會觸發

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM