绑定属性并在冗长的操作中使用它们

时间:2016-02-02 13:17:53

标签: multithreading javafx

在我的JavaFX应用程序中,我想在刷新数据库中的数据时禁用几个按钮。

我正在使用我要禁用的按钮的disableProperty

这是基本的JavaFX应用程序,用于说明我的观点:

public class BindLengthy extends Application {

BooleanProperty disable = new SimpleBooleanProperty(false);

@Override
public void start(Stage primaryStage) {
    Button btn = new Button();
    btn.setText("Say 'Hello World'");
    btn.disableProperty().bind(disable);
    btn.setOnAction(new EventHandler<ActionEvent>() {

        @Override
        public void handle(ActionEvent event) {
            disable.set(true);
            try {
                Thread.sleep(5000);
            } catch (InterruptedException ex) {
                Logger.getLogger(BindLengthy.class.getName()).log(Level.SEVERE, null, ex);
            }
            btn.setText("Done");
        }
    });

    //Do all the other stuff that needs to be done to launch the application
    //Like adding btn to the scene and so on...
    primaryStage.show();
}

/**
 * @param args the command line arguments
 */
public static void main(String[] args) {
    launch(args);
}

执行时,点击按钮会停留在&#34;触发&#34;模式,等待5秒,然后更改文本和禁用。虽然我希望稍后更改文本,但我想禁用“属性更改”以立即生效!

我尝试将由Thread.sleep(5000)表示的冗长操作放入任务并在new Thread(task)上启动,但显然文本在线程唤醒之前发生了变化。

我无法将btn.setText("Done")放入Thread,因为它不会在JavaFX-Thread(它需要)上执行。所以我尝试加入Thread,但是它给出的结果与不将它放入额外的Thread一样。

如何在执行长时间操作之前强制diableProperty注册新值?

1 个答案:

答案 0 :(得分:1)

使用Task并使用其onSucceeded处理程序更新用户界面:

public class BindLengthy extends Application {

    BooleanProperty disable = new SimpleBooleanProperty(false);

    @Override
    public void start(Stage primaryStage) {
        Button btn = new Button();
        btn.setText("Say 'Hello World'");
        btn.disableProperty().bind(disable);
        btn.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                disable.set(true);

                Task<String> task = new Task<String>() {
                    @Override
                    public String call() throws Exception {
                        Thread.sleep(5000);
                        return "Done" ;
                    }
                });

                task.setOnFailed(e ->
                    Logger.getLogger(BindLengthy.class.getName())
                          .log(Level.SEVERE, null, task.getException()));

                task.setOnSucceeded(e -> {
                    btn.setText(task.getValue());
                    disable.set(false);
                });

                Thread t = new Thread(task);
                t.setDaemon(true);
                t.start();
            }
        });

        //Do all the other stuff that needs to be done to launch the application
        //Like adding btn to the scene and so on...
        primaryStage.show();
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        launch(args);
    }

}