2011-08-31 87 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