2013-04-05 42 views
2

這是我在這裏的第一篇文章,所以希望它沒有問題。嘗試使用線程時程序鎖定

我在netbeans。我用鈕釦等做了一個窗口。

我有一個叫SimpleThread類,看起來像這樣:

public class SimpleThread extends Thread { 

public SimpleThread() 
{ 

} 

@Override 
public void run() 
{ 

} 

而且我有各種不同的子類的線程擴展simplethread(TimerThread,MouseGrabThread)。

public class MouseGrabThread extends SimpleThread{ 

private Point pt; 
private JTextField x, y; 

public MouseGrabThread(JTextField x, JTextField y) 
{ 
    super(); 
    this.x = x; 
    this.y = y; 
} 

@Override 
public void run() 
{ 
    while(this.isAlive()) 
    { 
     int[] xyVal = new int[2]; 
     xyVal = getCoords(); 
     x.setText("" + xyVal[0]); 
     y.setText("" + xyVal[1]); 
    } 
} 

public int[] getCoords() 
{ 
    Point pt = MouseInfo.getPointerInfo().getLocation(); 

    int[] retArr = new int[2]; 
    retArr[0] = (int)pt.getX(); 
    retArr[1] = (int)pt.getY(); 

    return retArr; 

} 



public class TimerThread extends SimpleThread { 

private JTextArea label; 
private int time; 

public TimerThread(JTextArea label, int time) 
{ 
    super(); 
    this.label = label; 
    this.time = time; 
} 

@Override 
public void run() 
{ 
    int counter = time; 
    while(counter != -1) 
    { 

     label.setText("You have: " + counter + " seconds until the timer ends!\n"); 
     counter--; 
     try { 
      this.sleep(1000); 
     } catch (InterruptedException ex) { 
      System.out.println("Thread Interrupted"); 
     } 

    } 
    stop(); 
} 

在我的UI窗口類,我有這樣的:

private void jButton2MouseClicked(java.awt.event.MouseEvent evt) {          
    SimpleThread timer = new TimerThread(jTextArea1, 10); //This counts down from 10 seconds and updates a status text box each second 
    SimpleThread mouseGrab = new MouseGrabThread(jTextField1, jTextField2); //This grabs mouse coords and updates two boxes in the UI. 
    timer.start(); 
    if(timer.isAlive()) 
    { 
     mouseGrab.start(); 
    } 
    while(timer.isAlive())//###### 
    { 
     if(!mouseGrab.isAlive()) 
     { 
      mouseGrab.start(); 
     } 
    } 

}

程序凍結10秒鐘時,我按下按鈕。

我猜我已標記的行(// #####)是導致UI在定時器的持續時間內凍結的行,導致它在主線程中運行。我不知道如何解決這個問題。

請原諒我對編程知識的缺乏,現在我正在進入自己的線程,而我正在大學學習關於數據結構的非常簡單的課程。如果可能的話,你能儘可能地「減弱」答案嗎?另外,我知道我做這件事很糟糕,但我稱之爲stop()函數,即使它不好(不要爲此拍攝我,我不知道該怎麼辦!)如果有人能夠很好地回答這個問題,那太棒了!

回答

1

,你可能想在倒計時結束時結束mouseGrab什麼:

private void jButton2MouseClicked(java.awt.event.MouseEvent evt) {          
    SimpleThread timer = new TimerThread(jTextArea1, 10); //This counts down from 10 seconds and updates a status text box each second 
    SimpleThread mouseGrab = new MouseGrabThread(jTextField1, jTextField2); //This grabs mouse coords and updates two boxes in the UI. 

    mouseGrab.start(); 
    timer.start(); 

    // Wait until countdown finishes 
    while(timer.isAlive()) {} 

    mouseGrab.stop(); 
} 

在您粘貼代碼,你不停地開始你的mouseGrabtimer正在運行。您可能更希望在定時器打開時讓鼠標抓取運行。

編輯:的確,stop()已被棄用,你真的應該在你的TimerThread使用boolean running屬性,並在一些

while (running) { 
    /* stuff */ 
} 

包裹其run()方法的內容,然後從外部「停止」這個帖子一些二傳手。那麼正確答案將是例如:

mouseGrab.start(); 
    timer.start(); 

    // Wait until countdown finishes 
    while(timer.isAlive()) {} 

    mouseGrab.setRunning(false); 
} 

EDIT2:這最終似乎是你想要什麼:

private void jButton2MouseClicked(java.awt.event.MouseEvent evt) {          
    SimpleThread mouseGrab = new MouseGrabThread(jTextField1, jTextField2); //This grabs mouse coords and updates two boxes in the UI. 
    SimpleThread timer = new TimerThread(mouseGrab, jTextArea1, 10); //This counts down from 10 seconds and updates a status text box each second 

    mouseGrab.start(); 
    timer.start(); 
} 

有了:

public class MouseGrabThread extends SimpleThread { 

    private Point pt; 
    private JTextField x, y; 
    private boolean running; 

    public MouseGrabThread(JTextField x, JTextField y) { 
     super(); 
     this.x = x; 
     this.y = y; 
    } 

    @Override 
    public void run() { 
     running = true; 
     while(running) { 
      int[] xyVal = new int[2]; 
      xyVal = getCoords(); 
      x.setText("" + xyVal[0]); 
      y.setText("" + xyVal[1]); 
     } 
    } 

    public int[] getCoords() { 
     Point pt = MouseInfo.getPointerInfo().getLocation(); 

     int[] retArr = new int[2]; 
     retArr[0] = (int)pt.getX(); 
     retArr[1] = (int)pt.getY(); 

     return retArr; 

    } 

    public void break() { 
     this.running = false; 
    } 
} 


// ------------- // 


public class TimerThread extends SimpleThread { 

    private MouseGrabThread mouseGrab; 
    private JTextArea label; 
    private int time; 

    public TimerThread(MouseGrabThread mouseGrab, JTextArea label, int time) 
    { 
     super(); 
     this.label = label; 
     this.time = time; 
     this.mouseGrab = mouseGrab; 
    } 

    @Override 
    public void run() 
    { 
     int counter = time; 
     while(counter != -1) 
     { 
      label.setText("You have: " + counter + " seconds until the timer ends!\n"); 
      counter--; 
      try { 
       this.sleep(1000); 
      } catch (InterruptedException ex) { 
       System.out.println("Thread Interrupted"); 
      } 

     } 

     mouseGrab.break(); 
    } 
} 
+0

如果我想繼續GUI在倒計時時可用嗎?現在,整個程序凍結,並且它不更新timerThread輸出的文本框或鼠標座標的X和Y textAreas。 – Pilapodapostache 2013-04-05 18:31:54

+0

您的'TimerThread'可以引用'mouseGrab',因此'timer'本身可以決定何時打破它。請參閱我的(傳入)** Edit2 **的插圖。 – blint 2013-04-05 18:55:01

+0

就是這樣,謝謝! :) – Pilapodapostache 2013-04-06 19:31:26

0

還有a better way to cancel a thread than calling stop,但是在你的TimerThread代碼中線程正在退出,所以我沒有看到這一點。一旦你的執行結束了run方法,那麼你的線程就完成了。對於MouseGrabThread,blint's answer是正確的,你應該結束該線程,但我不同意使用標誌,canceling the thread using interrupt是一個更好的解決方案。

另外在Swing中,您不應該更新除AWT線程外的Swing組件。請參閱this question。更改您的代碼是這樣的:

while(counter != -1) 
{ 
    java.awt.EventQueue.invokeLater(new Runnable() { 
     public void run() { 
      label.setText("You have: " + counter 
      + " seconds until the timer ends!\n"); 
     } 
    }); 
    counter--; 
    // etc. 

這種方式,你都在不斷下降的AWT隊列該事件線程可以把它撿起來,並運行新的任務。您可能也需要爲MouseInfo代碼執行此操作。

考慮使用Executor而不是啓動自己的線程。

我不確定您的響應問題在哪裏。不要太快地假設你的代碼卡在哪裏,添加一些printlns來確認發生了什麼(意識到在某些情況下添加它們可能會改變事物的時間)。也刪除這些線程中的一些,並逐漸添加它們以查看會發生什麼。