2011-08-31 90 views
9

我做了一個二十一點遊戲,並且我希望AI玩家在獲取卡之間暫停。我試着簡單地使用Thread.sleep(x),但是這會讓它凍結,直到AI玩家完成所有的卡片。我知道Swing不是線程安全的,所以我查看了Timers,但我無法理解如何使用它。這裏是我當前的代碼:如何在Swing中創建延遲

while (JB.total < 21) { 

      try { 
      Thread.sleep(1000); 
      } catch (InterruptedException ex) { 
      System.out.println("Oh noes!"); 
      } 

      switch (getJBTable(JB.total, JB.aces > 0)) { 
      case 0: 
       JB.hit(); 
       break; 
      case 1: 
       break done; 
      case 2: 
       JB.hit(); 
       JB.bet *= 2; 
       break done; 
      } 
     } 

順便說一句,hit();方法更新GUI。

回答

3

好了,下面的代碼顯示了一個JTextArea和一個JButton的JFrame。當按鈕被點擊時,Timer重複發送事件(在它們之間有第二個延遲)到與按鈕相關的actionListener,該按鈕用當前時間附加一行。

import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.Calendar; 

import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JTextArea; 
import javax.swing.Timer; 


public class TimerTest extends JFrame implements ActionListener{ 

    private static final long serialVersionUID = 7416567620110237028L; 
    JTextArea area; 
    Timer timer; 
    int count; // Counts the number of sendings done by the timer 
    boolean running; // Indicates if the timer is started (true) or stopped (false) 

    public TimerTest() { 
     super("Test"); 
     setBounds(30,30,500,500); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setLayout(null); 

     area = new JTextArea(); 
     area.setBounds(0, 0, 500, 400); 
     add(area); 

     JButton button = new JButton("Click Me!"); 
     button.addActionListener(this); 
     button.setBounds(200, 400, 100, 40); 
     add(button); 

     // Initialization of the timer. 1 second delay and this class as ActionListener 
     timer = new Timer(1000, this); 
     timer.setRepeats(true); // Send events until someone stops it 
     count = 0; // in the beginning, 0 events sended by timer 
     running = false; 
     System.out.println(timer.isRepeats()); 
     setVisible(true); // Shows the frame 
    } 

    public void actionPerformed(ActionEvent e) { 
     if (! running) { 
      timer.start(); 
      running = true; 
     } 
     // Writing the current time and increasing the cont times 
     area.append(Calendar.getInstance().getTime().toString()+"\n"); 
     count++; 
     if (count == 10) { 
      timer.stop(); 
      count = 0; 
      running = false; 
     } 
    } 

    public static void main(String[] args) { 
     // Executing the frame with its Timer 
     new TimerTest(); 
    } 
} 

那麼,這段代碼是一個如何使用javax.swig.Timer對象的例子。關於這個問題的具體情況。 if語句停止定時器必須改變,顯然,actionPerformed的動作。下面的片段是解決方案的骨架的actionPerformed:

public void actionPerformed(ActionEvent e) { 
    if (e.getComponent() == myDealerComponent()) { 
    // I do this if statement because the actionPerformed can treat more components 
     if (! running) { 
      timer.start(); 
      runnig = true; 
     } 
     // Hit a card if it must be hitted 
     switch (getJBTable(JB.total, JB.aces > 0)) { 
      case 0: 
       JB.hit(); 
       break; 
      case 1: 
       break done; 
      case 2: 
       JB.hit(); 
       JB.bet *= 2; 
       break done; 
     } 
     if (JB.total >= 21) { // In this case we don't need count the number of times, only check the JB.total 21 reached 
      timer.stop() 
      running = false; 
     } 

    } 
} 

恕我直言,這樣可以解決問題,現在@ user920769必須考慮放在哪裏的ActionListener和啓動/停止條件......

@kleopatra:謝謝爲表明我這個定時器類的存在,我不知道任何關於它和它的神奇,讓可能有很多的任務東西放到一個Swing應用程序:)

+0

非常感謝你的例子,但是我得到這些行的錯誤:timer = new Timer(1000,this); timer.setRepeats(真);說它無法分別找到合適的構造函數或方法。他們是否被棄用? – Fractaly

+0

你導入Timer類嗎?這些方法即使在上一個版本中也不會被棄用,因此這似乎是您的錯誤。 [這裏是Java7 ApiDoc](http://download.oracle.com/javase/7/docs/api/javax/swing/Timer.html) – Charliemops

7

所以我看着計時器,但我不明白我怎麼會用一個此

定時器是解決方案,因爲你說你正在更新應在完成GUI EDT。

我不確定你關心的是什麼。你交易一張卡並啓動計時器。當計時器啓動時,您決定拿走另一張卡或按住。當你堅持你的計時器。

+0

感謝,但我能不能給我一些示例代碼關於如何使用這個計時器?我之前嘗試過,它拋出一個錯誤,我忘記了究竟是什麼。 – Fractaly

+0

@ user920769看到(並仔細閱讀;)再次錯誤,重試 – kleopatra

3

我認爲在this tutorial清楚如何使用定時器,以達到你想要什麼,而不必處理線程。

+1

ESTA respuesta ES德拉布埃納 – alex

4

那麼,關於定時器的快速解釋。

首先,您需要在您的類中使用java.util.Timer變量,並且在您的項目中需要另一個類,該類繼承自java.util.TimerTask(我們稱之爲Tasker)。

定時器變量的初始化是那麼容易:

Timer timer = new Timer(); 

現在塔斯克類:

public class Tasker extends TimerTask { 
    @Override 
    public void run() { 
     actionToDo(); // For example take cards 
    } 

    // More functions if they are needed 
} 

最後,與其相關的Tasker計時器安裝:

long delay = 0L; 
long period = pauseTime; 
timer.schedule(new Tasker(),delay,period); 

時間表功能指示以下內容: Fisrt參數:對d o每個週期毫秒(執行TimerTask類或其擴展的運行功能) 第二個參數:定時器必須啓動。在這種情況下,它會在調用調度函數時啓動。以下示例表示在調用計劃函數後1秒開始:timer.schedule(new Tasker(),1000,period); 第三參數:Tasker.run()函數的一次調用與以下調用之間的毫秒數。

我希望你能理解這個microtutorial :)。如果您有任何問題,請提供更詳細的信息!

親切的問候!

+0

(編輯刪除:-)實際上是專制 - 你很少在Swing使用util.Timer,而是使用swingx。定時器或(對於更復雜的後臺任務)SwingWorker – kleopatra

+0

@kleopatra'swingx.Timer'(scratches head)DYM'javax.swing.Timer'?不能說我遇到了另一個。 –

+0

那麼,我把代碼與util.Timer,因爲是我在一年前的項目中使用。我的項目是一個voleyball遊戲,我們使用上述結構重新計算信息並每隔0.04秒刷新一次窗口。我不知道如何使用swingx.Timer,但是這個代碼在圖形應用程序中正常工作。它不會凍結窗口並讓用戶毫無問題地完成任務。 =) – Charliemops