为什么您的代码不起作用
您的代码不起作用的原因是您阻止了FX Application Thread。
与所有UI工具包一样(几乎?),JavaFX是单线程UI工具包。这意味着所有事件处理程序以及UI的所有呈现都在单个线程(称为FX Application
Thread)上执行。
在您的代码中,您有一个事件处理程序需要花一秒钟以上的时间来运行,因为它通过调用暂停一秒钟
Thread.sleep(...)。在该事件处理程序运行时,无法重绘UI(因为单个线程无法一次执行两项操作)。因此,尽管按钮文本的值立即更改,但是直到该
handle(...)方法完成运行后,新值才会真正显示在屏幕上。如果
forhandle方法中有一个循环,则在整个循环(以及该方法中的任何其他内容)完成之前,不会呈现任何内容。
如何修复
在JavaFX中执行所需操作的最简单方法是使用a
Timeline处理暂停。在
Timeline为你适当地管理线程:
import javafx.animation.Keyframe;import javafx.animation.Timeline;import javafx.application.Application;import javafx.scene.Scene;import javafx.scene.control.Button;import javafx.scene.layout.StackPane;import javafx.stage.Stage;import javafx.util.Duration;public class CountingButton extends Application { @Override public void start(Stage primaryStage) { Button button = new Button("Count"); Timeline timeline = new Timeline(); for (int count = 0; count <= 5 ; count++) { final String text = Integer.toString(count); Keyframe frame = new Keyframe(Duration.seconds(count), event -> button.setText(text)); timeline.getKeyframes().add(frame); } button.setonAction(e -> timeline.play()); primaryStage.setScene(new Scene(new StackPane(button), 120, 75)); primaryStage.show(); } public static void main(String[] args) { launch(args); }}通常,对于更改特定时间点的用户界面外观,JavaFX Animation
API(另请参见教程)可能会很有用,尤其是
Timeline和
PauseTransition。
一种“较低级别”的方法是创建
Thread自己并在该线程中暂停。这要先进得多:您需要小心地在FX
Application线程上而不是在您创建的线程上更新UI。您可以通过以下方式进行此操作
Platform.runLater(...):
import javafx.application.Application;import javafx.application.Platform;import javafx.beans.property.IntegerProperty;import javafx.beans.property.SimpleIntegerProperty;import javafx.scene.Scene;import javafx.scene.control.Button;import javafx.scene.layout.StackPane;import javafx.stage.Stage;public class CountingButton extends Application { @Override public void start(Stage primaryStage) { Button button = new Button("Start"); button.setonAction(e -> { Thread thread = new Thread(() -> { for (int i = 0; i <= 5 ; i++) { final String text = "Count: "+i ; Platform.runLater(() -> button.setText(text)); try { Thread.sleep(1000); } catch (InterruptedException exc) { exc.printStackTrace(); } } }); thread.start(); }); primaryStage.setScene(new Scene(new StackPane(button), 120, 75)); primaryStage.show(); } public static void main(String[] args) { launch(args); }}


