javafx how to use thread in fxml controller


Question

I want to use thread I can use in simple program, but I can't use threads in fxml controller

Simple program:

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package javafxapplication3;

import java.util.Timer;
import java.util.TimerTask;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

/**
 *
 * @web http://java-buddy.blogspot.com/
 */
public class JavaFX_TimerTask extends Application {

    final int MAX = 100;

    Thread myTaskThread;
    Thread myRunnableThread;
    Timer myTimer;

    MyTask myTask;
    MyRunnable myRunnable;
    MyTimerTask myTimerTask;

    @Override
    public void start(Stage primaryStage) {

        myTask = new MyTask();
        ProgressBar progressBarTask = new ProgressBar();
        progressBarTask.setProgress(0);
        progressBarTask.progressProperty().bind(myTask.progressProperty());

        ProgressBar progressBarRunnable = new ProgressBar();
        progressBarRunnable.setProgress(0);
        myRunnable = new MyRunnable(progressBarRunnable);

        ProgressBar progressBarTimerTask = new ProgressBar();
        progressBarTimerTask.setProgress(0);
        myTimerTask = new MyTimerTask(progressBarTimerTask);

        Button btnStart = new Button("Start Task");
        btnStart.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent t) {
                myTaskThread = new Thread(myTask);
                myTaskThread.start();

                myRunnableThread = new Thread(myRunnable);
                myRunnableThread.start();

                myTimer = new Timer();
                myTimer.scheduleAtFixedRate(myTimerTask, 80, 100);
            }
        });

        VBox vBox = new VBox();
        vBox.setPadding(new Insets(5, 5, 5, 5));
        vBox.setSpacing(5);
        vBox.getChildren().addAll(
                new Label("Run in Thread(Task)"),
                progressBarTask,
                new Label("Run in Thread(Runnable)"),
                progressBarRunnable,
                new Label("Run in Timer and TimerTask"),
                progressBarTimerTask,
                btnStart);

        StackPane root = new StackPane();
        root.getChildren().add(vBox);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("java-buddy.blogspot.com");
        primaryStage.setScene(scene);
        primaryStage.show();

    }

    public static void main(String[] args) {
        launch(args);
    }

    class MyTask extends Task<Void>{

        @Override
        protected Void call() throws Exception {
            for (int i = 1; i <= MAX; i++) {
                updateProgress(i, MAX);
                Thread.sleep(100);
            }
            return null;
        }

    }

    class MyRunnable implements Runnable{

        ProgressBar bar;

        public MyRunnable(ProgressBar b) {
            bar = b;
        }

        @Override
        public void run() {
            for (int i = 1; i <= MAX; i++) {

                final double update_i = i;

                //Not work if update JavaFX UI here!
                //bar.setProgress(i/MAX);

                //Update JavaFX UI with runLater() in UI thread
                Platform.runLater(new Runnable(){

                    @Override
                    public void run() {
                        bar.setProgress(update_i/MAX);
                    }
                });

                try {
                    Thread.sleep(100);
                } catch (InterruptedException ex) {
                    Logger.getLogger(JavaFX_TimerTask.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }

    }

    class MyTimerTask extends TimerTask{

        ProgressBar bar;
        double count;

        public MyTimerTask(ProgressBar b) {
            bar = b;
            count = 0;
        }

        @Override
        public void run() {

            bar.setProgress(count++/MAX);

            if(count >= MAX){
                myTimer.cancel();
            }

        }

    }

}

Now, I want to use thread in a fxml controller:

public class DashboardController implements Initializable {
     @Override
        public void initialize(URL url, ResourceBundle rb) {




        } 

   }

When I use thread, in initialize it doesn't show me any output.

How can I use thread?

Thank you.

1
0
7/6/2014 2:55:06 PM

Accepted Answer

Is your Controller initialized?

Do you set it (in the fxml/FXMLoader)?

If it your Controller is loaded this should work.

public class DashboardController implements Initializable {
 @Override
    public void initialize(URL url, ResourceBundle rb) {
        myTask = new MyTask();
         myTaskThread = new Thread(myTask);
         myTaskThread.start();


    } 
}
0
7/7/2014 9:11:45 AM

JavaFx already runs threads -

  1. JavaFx thread for GUI
  2. Launch thread for background services.

If you need to make something like progress bar in which you want to run something over javafx thread then i would suggest use Services instead of thread as it can be used again and again while threads can't be.

Service<Void> ser = new Service<Void>() {
        @Override protected Task createTask() {
            return new Task<Void>() {
            @Override protected Void call() throws InterruptedException {
                // You code you want to execute in service backgroundgoes here
                return null;
                }
            };
         }
};
ser.setOnSucceeded((WorkerStateEvent event) -> {
    // Anything which you want to update on javafx thread (GUI) after completion of background process.
});
ser.start();

You can use the service again and again with any variation like loop/recursion/switch -

ser.restart(); // Restart the service
ser.reset(); // Stops the service

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon