JavaFX, problem with Platform.runLater(), delayed rendering of Canvas graphic

时间:2018-09-18 20:13:45

标签: java user-interface javafx event-handling

I am trying to make a simple event driven TicTacToe game using JavaFX. Currently I am struggling with termination once certain conditions are met. To put it into more details, the player can click on the GridPane elements, which are Canvas Objects, and then they are filled with "X" or "O" shapes respectively (I am using strokeLine and strokeOval methods of GraphicsContext). Code below:

private static void placeX(Canvas square){
    GraphicsContext gc = square.getGraphicsContext2D();
    gc.setLineWidth(10.0f);
    gc.setStroke(Color.CORNFLOWERBLUE);
    gc.strokeLine(square.getWidth()*0.2, square.getHeight()*0.2, square.getWidth()*0.8, square.getHeight()*0.8);
    gc.strokeLine(square.getWidth()*0.8, square.getHeight()*0.2, square.getWidth()*0.2, square.getHeight()*0.8);
}

Once 3 of the same shapes appear in line or diagonally the program should terminate. I am doing this using Platform.exit(). Code below:

class HandleGame implements EventHandler<MouseEvent>{

    @Override
    public void handle(MouseEvent e){


        Canvas can = (Canvas)e.getTarget();
        //function to check if the canvas is clear 
             placeX(can);  

         if(game.isEnded()){  //checks if the same shape appears three times

            Platform.runLater(new Runnable() {
                @Override
                public void run(){
                    try {
                        Thread.sleep(5000);
                    }
                    catch(InterruptedException exc){
                        System.out.println("Got something: " + exc.getMessage());
                    }
                    Platform.exit();
                }
            });
        }
    } 
}

This event handler is attached to every Canvas object in GridPane and triggers on mouse release. The problem I am having is that once the last Canvas is clicked, before the shape appears on the Canvas the specified Runnable is executed and the rendering is unnaturally delayed (the "X" shape appears only for a second before closing). Strangely enough 1 out of 10 runs it executes as expected. How can I make the rendering trigger before the Thread.sleep() and following Platform.exit()? Why on rare occasions the rendering is actually performed before Thread.sleep()? I did a little research but could not find anything decisive, I am newbie when it comes to JavaFx. Appreciate your help.

1 个答案:

答案 0 :(得分:0)

基于@Slaw和@VGR注释,我设法使用两种不同的方法解决了该问题,一种方法是使用PauseTransition,第二种方法是Thread。下面的代码:

使用PauseTransition

if(game.isEnded()){
    PauseTransition termination = new PauseTransition(Duration.seconds(1d));
    termination.setOnFinished(event -> Platform.exit());
    termination.play();
}

使用Thread

if(game.isEnded()){

    new Thread(() -> {
        try{
            Thread.sleep(2000);
        }
        catch(InterruptedException exc){
            ; //exception handling code here
        }
        Platform.exit();       
    }).start();*/