如何在Swing中创build延迟

我做了一个二十一点的游戏,我希望AI玩家在拿牌之间暂停一下。 我试着简单地使用Thread.sleep(x),但是这会让它冻结,直到AI玩家完成所有的卡片。 我知道Swing不是线程安全的,所以我看了一下Timers,但是我不明白怎样才能使用它。 这是我现在的代码:

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; } } 

顺便说一句,命中(); 方法更新GUI。

那么,下面的代码显示了带有JTextArea和JButton的JFrame。 当button被点击时,Timer重复发送事件(在它们之间有第二个延迟)到与button相关的actionListener,该button用当前时间附加一行。

 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的行为。 以下片段是解决schemeactionPerformed的骨架:

 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应用程序:)

所以我看着计时器,但我不明白我怎么能用这个

定时器是解决scheme,因为正如你所说,你正在更新应该在EDT上完成的GUI。

我不确定你的担心是什么 你交易一张卡并启动计时器。 当定时器启动时,您决定拿走另一张卡或按住。 当你保持停止计时器。

那么,关于定时器的快速解释。

首先,您需要在您的类中使用java.util.Timervariables,并在您的项目中使用java.util.TimerTask(让我们称之为Tasker)的另一个类。

Timervariables的初始化非常简单:

 Timer timer = new Timer(); 

现在Tasker类:

 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 param:执行每个周期毫秒的动作(执行TimerTask类或其扩展的运行函数)第二个参数:当定时器必须启动时。 在这种情况下,它会在调度日程function时启动。 下面的例子表示调用schedule函数后1秒开始: timer.schedule(new Tasker(),1000,period); 第三个参数:一个Tasker.run()函数调用和下面的调用之间的毫秒数。

我希望你能理解这个microtutorial :)。 如果您有任何问题,请提供更详细的信息!

亲切的问候!

我认为在这个教程中很清楚如何使用定时器来实现你想要的,而不必处理线程。