我正在为 Java 类(class)的最后一个项目创建一个黑 jack 程序,我想模拟荷官在一轮结束时给自己发牌。我想让 while 循环的每次迭代 hibernate 1 秒以显示轻微的暂停。以下是我根据我在堆栈溢出上读到的不同线程进行的两次尝试,但都不起作用。
Timeline timeline = new Timeline(
new KeyFrame(Duration.millis(1000), event ->
{
if(dealer.getScore() < 17 || (dealer.getScore() < player.getScore() && dealer.getScore() <= 21))
{
newCard(dealer, mainDeck.deal(), false);
System.out.println("Running Here!");
LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining");
}
})
);
timeline.setCycleCount(1);
System.out.println("Starting loop!");
还有这个:
while (dealer.getScore() < 17 || (dealer.getScore() < player.getScore() && dealer.getScore() <= 21))
{
new Thread(() ->
{
try
{
Thread.sleep(1000);
newCard(dealer, mainDeck.deal(), false);
LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining");
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}).run();
}
我不太确定第一个示例有什么问题,因为我以前从未使用过时间线。至于第二个,它似乎计算了总 sleep 时间并在该持续时间内卡住我的程序。 IE。如果循环进行 3 次,我的程序会 hibernate 3 秒,然后继续。然后它立即吐出所有标签。
最佳答案
您的时间轴仅执行一次,因为它只有一个 KeyFrame
,并且您将周期计数设置为 1
(因此整个时间轴执行一次)。
您可以将周期计数设置为INDEFINITE
(因此它会永远重复),并在满足条件时显式停止时间线:
Timeline timeline = new Timeline();
KeyFrame keyFrame = new KeyFrame(Duration.millis(1000), event -> {
if(dealer.getScore() >= 17 && (dealer.getScore() >= player.getScore() || dealer.getScore() > 21)) {
timeline.stop();
} else {
newCard(dealer, mainDeck.deal(), false);
System.out.println("Running Here!");
LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining");
}
});
timeline.getKeyFrames().add(keyFrame);
timeline.setCycleCount(Animation.INDEFINITE);
timeline.play();
您的线程解决方案有几个问题。首先,您根本没有在后台线程上运行线程的可运行对象:Thread.run()
只是在当前线程(即 FX 应用程序线程)上执行可运行对象。因此,您的 Thread.sleep() 会阻塞 FX 应用程序线程,导致 UI 无法渲染并变得无响应。要实际启动新线程,您应该调用 Thread.start()
。
第二个问题是您调用的 newCard()
和 setText()
方法会更改 UI,而您无法从后台线程执行此操作。您需要在 FX 应用程序线程上执行这些操作:您可以通过将它们包装在 Platform.runLater(...)
中来执行此操作。
最后,您将为您处理的每张牌创建一个新线程,并且(一旦修复)启动该线程。因此,每张牌基本上都会同时发出,每个线程一张。这不是您想要的:您希望后台线程一次处理一张牌并在每张牌之间暂停。因此,创建一个后台线程并在其中运行整个循环:
new Thread(() -> {
while (dealer.getScore() < 17 || (dealer.getScore() < player.getScore() && dealer.getScore() <= 21)) {
try {
Thread.sleep(1000);
newCard(dealer, mainDeck.deal(), false);
LBLDeck.setText(String.valueOf(mainDeck.getRemaingCards()) + " cards remaining");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
关于JavaFX 显示新标签然后 hibernate 循环的每次迭代,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44091316/