About statement Thread.sleep()

Đặng Huy :

I try to make an application that show an button. When I click the button , the scene should show a text ( add a label) for a few seconds, and then the text disappear (remove the label from the scene). But in fact when I click the button, nothing happens. I am really in this trouble for days. Please help me.

public class Main extends Application {

@Override
public void start(Stage primaryStage) throws Exception{
    StackPane pane = new StackPane();
    Button btn = new Button();
    Label lb = new Label("Start");
    pane.getChildren().addAll(btn);
    primaryStage.setTitle("Hello World");
    primaryStage.setScene(new Scene(pane, 300, 275));
    primaryStage.show();
    btn.setOnAction(e->{
         pane.getChildren().addAll(lb);
        try {
            Thread.sleep(300);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
       pane.getChildren().removeAll(lb);
    });
}
public static void main(String[] args) {
    launch(args);
}
}
James_D :

Use a PauseTransition:

btn.setOnAction(e->{
    pane.getChildren().addAll(lb);
    PauseTransition pause = new PauseTransition(Duration.seconds(0.3));
    pause.setOnFinished(e -> pane.getChildren().removeAll(lb));
    pause.play();
});

The reason your approach doesn't work, is that JavaFX effectively uses a single thread for rendering and handling user events. It will update the screen at a fixed interval (60 times per second in the current implementation), but for synchronization reasons has to wait for any pending events that are currently being handled to complete first. So you original code adds the label, pauses for 0.3 seconds, and then removes the label. The FX Application Thread is occupied for this whole process, so the FX framework never has an opportunity to redraw the scene while it is happening.

The bottom line here is that you should never block the FX application thread, by calling sleep() or by executing long-running operations.

Update in response to additional question in comment:

To disable all event handling, you can call setDisable(true) on the root node of the scene. So to prevent event handling while the label is shown:

btn.setOnAction(e->{
    pane.getChildren().addAll(lb);
    pane.setDisable(true);
    PauseTransition pause = new PauseTransition(Duration.seconds(0.3));
    pause.setOnFinished(e -> {
        pane.getChildren().removeAll(lb));
        pane.setDisable(false);
    });
    pause.play();
});

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=396401&siteId=1