为什么thread.sleep会破坏我的JavaFX应用程序?

为什么thread.sleep会破坏我的JavaFX应用程序?,java,javafx,thread-sleep,Java,Javafx,Thread Sleep,我有一个for循环,循环遍历我游戏中的所有玩家。在下一次迭代之前,我想让当前播放器用3分钟进行选择(这是canvas mouseclick事件)。我尝试过的一切都会使我的应用程序崩溃,没有错误。我已经做了好几个小时了,不知道发生了什么。我做错了什么 startGame.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() { @O

我有一个for循环,循环遍历我游戏中的所有玩家。在下一次迭代之前,我想让当前播放器用3分钟进行选择(这是canvas mouseclick事件)。我尝试过的一切都会使我的应用程序崩溃,没有错误。我已经做了好几个小时了,不知道发生了什么。我做错了什么

    startGame.addEventHandler(MouseEvent.MOUSE_CLICKED,
                new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent e) {

                gameStatus = "Started";
                players.add(new Player(0, "Amrit"));
                players.add(new Player(1, "Tyler"));
                players.add(new Player(2, "Scott"));
                players.add(new Player(3, "Ryker"));

                //Select first two settlements with one road extending from each
                for (int s = 0; s < 2; s++) {

                    for (int p = 0; p < players.size(); p++) {

                        phase = "Pick Settlements";
                        playerTurn = p;

                        //Loop through all tiles
                        for (int t = 0; t < tiles.length; t++) {

                            //Loop through the vertices of the current tile
                            for (int v = 0; v < tiles[t].vertices.length; v++) {

                                drawCircle(gc, new Point(tiles[t].vertices[v].x, tiles[t].vertices[v].y), (int) (windowHeight * .05), true, true, "rgba(255, 238, 144, .3)", 0);

                            }

                        }

                        gc.setFill(Color.web("0xFFEB8A"));
                        gc.strokeText(players.get(p).name + ", please place your first settlement!", windowHeight * .95, windowWidth * .85);
                        selected = false;
                        canvas.addEventFilter(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
                            // @Override
                            @Override
                            public void handle(final MouseEvent event) {
                                if (!pointClicked().equals(0)) {
                                    players.get(playerTurn).settlementsAvail--;
                                    selected = true;
                                }
                            }

                        });

                        try 
                        {
                            Thread.sleep(1000 * 60 * 3);
                        } 
                        catch(InterruptedException er)
                        {
                             // this part is executed when an exception (in this example InterruptedException) occurs
                        }
                    }

                }

                gameStatus = "Ended";

            }

        });
startGame.addEventHandler(MouseEvent.MOUSE_单击,
新的EventHandler(){
@凌驾
公共无效句柄(MouseEvent e){
gameStatus=“已开始”;
玩家。添加(新玩家(0,“Amrit”);
添加(新玩家(1,“泰勒”);
添加(新玩家(2,“斯科特”);
添加(新玩家(3,“莱克”);
//选择前两个定居点,每个定居点延伸一条道路
对于(int s=0;s<2;s++){
对于(int p=0;p
您正在FX应用程序线程上睡觉。这将冻结整个GUI,使其无法处理用户输入。而是使用
时间线

Timeline timer = new Timeline(            
      new KeyFrame(Duration.seconds(60 * 3), event -> finishedSleeping())
);
timer.play();
或javafx
任务

Task<Void> timer = new Task<Void>() {
    @Override
    protected Void call() throws Exception {
       try {
            Thread.sleep(1000 * 60 * 3);
       } catch (InterruptedException e) {}
       return null;    
    }
};
timer.setOnSucceeded(event -> finishedSleeping());
new Thread(timer).start();
Task timer=新任务(){
@凌驾
受保护的Void调用()引发异常{
试一试{
线程睡眠(1000*60*3);
}捕获(中断异常e){}
返回null;
}
};
timer.setonSucceed(事件->FinishedLeaping());
新线程(计时器).start();

在本例中,睡眠发生在与FX应用程序线程不同的线程上<代码>FinishedLeaping()将在3分钟结束后在FX应用程序线程上调用。

是否确实要在实际的单击处理程序中睡眠?这可能会在相当一段时间内锁定整个程序(或至少锁定用户交互)。请发布实际的异常和错误消息。很抱歉,我不清楚这一点,但StartName处理程序与我希望留出时间的单击处理程序(画布)是分开的。canvas click处理程序在代码的下面一点。使用第一种方法,应用程序不再崩溃,但计时器什么也不做。一切照常进行。至于第二种方法,我得到了错误。具体来说:类型任务不接受参数,方法不重写或实现来自supertype@ShoeLace1291对于第二种方法,您必须导入
javafx.concurrent.Task
。这两种方法都应该很有效。从调用
timer.play()/新线程(timer.start())的位置开始调用示例中的
FinishedLeaping()
之前大约需要3分钟。当然,您需要实现一个事件处理程序(
event->finishedSleeping()
)来处理到达3分钟等待结束时的事件,而不是代码中当前的循环。好的,我最初使用的第一个方法导入了错误的任务类。但上述两种方法都没有任何作用。一切都立即执行。@ShoeLace1291当您插入两个方法之一的代码时,一切都在
timer.play()之后/新线程(计时器).start()将立即执行,因为睡眠发生在另一个线程上。这就是为什么必须放弃两个封闭for循环。替换为的代码将在3*60秒后执行。