2012-12-03 44 views
1

好吧我正在模擬運行。我在我的模擬的GUI上實現了兩個JButton,它們是actionListeners。我想要的是讓整個模擬暫停,如果我按下暫停按鈕,並恢復,如果我按下恢復按鈕。如何使用Swing暫停Java仿真

有多個線程正在運行,並且我試圖獲取每個線程並在點擊暫停按鈕時調用它們的wait()方法,但是我沒有成功這樣做。

因此,我需要一些建議如何做到這一點。我爲GUI使用Swing,並且偵聽器正常工作。我確實嘗試在View類的當前線程(使用MVC模式)上調用sleep()和wait()以查看發生了什麼,但導致整個應用程序崩潰。

任何想法?

回答

3

您需要爲模擬線程提供額外的邏輯,它將接受來自控制(GUI)線程的「信號」並等待下一個控制信號恢復執行。

例如,您可以在仿真線程中使用volatile boolean isPaused實例字段。將其設置爲true/false以暫停/恢復仿真線程。在仿真線程執行相應的邏輯:

public void run() { 
    while (true) { 
     simulate(); 
     while (isPaused) { 
      Thread.sleep(100); 
     } 
    } 
} 
+2

這個解決方案的問題是線程將每100毫秒喚醒一次,這會使用處理器時間。最好使用'wait()'和'notify()',它沒有這個問題。 – durron597

+0

我認爲等待/通知對於非常併發的環境更好。對於他的簡單任務,這個解決方案可以完成這項工作。 – hoaz

0

我想你可以創建一個ThreadGroup來存儲所有的線程,然後嘗試使用

ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();

順便說一句,ExecutorService是一個不錯的選擇,太多。

0

使用共享對象的兩個類之間進行通信。然後讓你的gui在點擊按鈕時設置狀態對象的值,並在再次點擊時再次更改它。下面是一些示例代碼:

public class Simulation implements Runnable { 
    private State myState = null; 

    public Simulation(State myState) { 
    this.myState = myState; 
    } 

    public void run() { 
    while(myState != null) { 
     if (myState.isPaused()) myState.wait(); 
     // Do other stuff 
    } 
    } 
} 

public class MainClass implements ActionListener() { 
    private State myState = new MyState(); 

    private void beginSimulation() { 
    Simulation s = new Simulation(this.myState()); 
    new Thread(s).start(); 
    } 

    public void actionPerformed(ActionEvent e) { 
    if(myState.isPaused()) { 
     myState.setPaused(false); 
     myState.notify(); 
    } else { 
     myState.setPaused(true); 
    } 
    } 
} 

public class MyState() { 
    private boolean paused = false; 
    public MyState(boolean paused) { this.paused = paused; } 
    public boolean getPaused() { return paused; } 
    public void setPaused(boolean paused) { this.paused = paused; } 
} 
2

如果動畫使用Swing的Timer簡單的答案是調用stop()

我強烈建議使用Timer進行動畫製作,因爲它可以確保動作在EDT上執行。

+0

反過來說,如果OP有一個問題中所述的模擬,那麼在EDT上運行它是一個壞主意,因爲模擬往往會導致處理器沉重並導致應用程序成爲無響應。 –