我正在为我的Java课程中的最终项目创建一个黑色插孔程序,我想模拟经销商在一轮结束时给自己的卡片。我想睡一个while循环的每次迭代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();
}
我不太确定第一个例子有什么问题,因为我之前从未使用过时间轴。至于第二个,它似乎计算睡眠时间的总量并冻结我的程序持续时间。 I.E.如果循环进行了3次我的程序睡眠3秒然后继续。然后它立即吐出所有标签。
答案 0 :(得分:1)
您的时间轴只执行一次,因为它只有一个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();
您的线程解决方案有几个问题。首先,你根本没有在后台线程上运行线程的runnable:Thread.run()
只是在当前线程上执行runnable,这是FX Application Thread。因此,您的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();