Peter Penzov
Peter Penzov

Reputation: 1670

Display message during loading

I have a JavaFX with TabPane which holds Java Objects with data into different tabs. I found that when the content of the tab takes time to load because there are SQL queries for execution the application just hangs. Is there any way to display some "Loading" message during the content utilization? for example:

Tab.setContent(<some_heavy_Java_Object>);

Is there any workaround to solve this in JavaFX or Java?

P.S I tested this code sample but I get error when I try to run the code:

TabContentInfrastructure content;

class GetDailySalesService extends Service<ObservableList<Object>>
{

    @Override
    protected Task createTask()
    {
        return new GetDailySalesTask();
    }
}

class GetDailySalesTask extends Task<ObservableList<Object>>
{

    @Override
    protected ObservableList<Object> call() throws Exception
    {

        content = new TabContentInfrastructure();

        return (ObservableList<Object>) content.initTestTabContentData();
    }
}

..........

            VBox vbox = new VBox();

            content = new TabContentInfrastructure();


            vbox.getChildren().add(content.initTestTabContentData());

            GetDailySalesService service = new GetDailySalesService();

            Region veil = new Region();
            veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
            veil.setPrefSize(240, 160);
            ProgressIndicator p = new ProgressIndicator();
            p.setMaxSize(140, 140);

            p.progressProperty().bind(service.progressProperty());
            veil.visibleProperty().bind(service.runningProperty());
            p.visibleProperty().bind(service.runningProperty());
            //tableView.itemsProperty().bind(service.valueProperty());

            StackPane stack = new StackPane();
            stack.getChildren().addAll(vbox, veil, p);

            service.start();

            tabdata.setContent(stack);

Can you help me to solve this issue.

Another attempt to solve the issue:

Task<VBox> task = new Task<VBox>()
                {
                    @Override
                    protected VBox call() throws Exception
                    {
                        TabContentInfrastructure content = new TabContentInfrastructure();


                        return content.initTestTabContentData();
                    }
                };

                Thread th = new Thread(task);
                th.setDaemon(true);
                th.start();

                Region veil = new Region();
                veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
                veil.setPrefSize(240, 160);
                ProgressIndicator p = new ProgressIndicator();
                p.setMaxSize(140, 140);

                //p.progressProperty().bind(service.progressProperty());
                veil.visibleProperty().bind(task.runningProperty());
                p.visibleProperty().bind(task.runningProperty());
                //vb.visibleProperty().bind(service.runningProperty().not());
                //tableView.itemsProperty().bind(service.valueProperty());

                StackPane stack = new StackPane();

                task.setOnSucceeded(new EventHandler<WorkerStateEvent>()
                {
                    @Override
                    public void handle(WorkerStateEvent t){

                        System.out.print("Entered setOnSucceeded**********" + t.getSource().getValue());
                        stack.getChildren().clear();
                        stack.getChildren().addAll(task.getValue());


                    }
                });

                stack.getChildren().addAll(veil, p);
                tabdata.setContent(stack);

This time the result is null.

And another unsuccessful attempt.

StackPane stack = new StackPane();
                Region veil = new Region();
                ProgressIndicator p = new ProgressIndicator();

                Task<VBox> task = new Task<VBox>()
                { // create new task
                    @Override
                    public VBox call() throws InterruptedException
                    {

                        Platform.runLater(new Runnable()
                        { // USE THIS INSTEAD

                            @Override
                            public void run()
                            {
                                try
                                {
                                    // ui updates here(inside application thread)
                                    // this is needed if you want to update your ui
                                    // you cannot update any ui from outside the application thread

                                    TabContentInfrastructure content = new TabContentInfrastructure();
                                    //stack.getChildren().clear();

                                    stack.getChildren().addAll(content.initTestTabContentData());
                                }
                                catch (InterruptedException ex)
                                {
                                    //Logger.getLogger(InfrastructureDataTabs.class.getName()).log(Level.SEVERE, null, ex);
                                }

                            }
                        });
                        return null;

                    }
                };

                new Thread(task).start();


                veil.setStyle("-fx-background-color: rgba(0, 0, 0, 0.4)");
                veil.setPrefSize(240, 160);

                p.setMaxSize(140, 140);

                p.progressProperty().bind(task.progressProperty());
                veil.visibleProperty().bind(task.runningProperty());
                p.visibleProperty().bind(task.runningProperty());
                //vb.visibleProperty().bind(service.runningProperty().not());
                //tableView.itemsProperty().bind(service.valueProperty());

               stack.getChildren().addAll(veil, p);

               tabdata.setContent(stack);

Upvotes: 0

Views: 1953

Answers (2)

ItachiUchiha
ItachiUchiha

Reputation: 36742

you must load the data in a different Task Thread, I see that you are trying to do the same. The problem with your code is that you are not updating your progress bar. You must use updateProgress as shown here

http://docs.oracle.com/javafx/2/threads/jfxpub-threads.htm#BABGJIDB

Here is a very nice example from Jewelsea where he has very nicely displayed the use of Task and how to use it to update the progress on the UI

Update progress bar and multiple labels from thread

Here you can find out how to use the Task as well as update the UI from the task

Some more Nice examples are

https://community.oracle.com/message/9927179#9927179

https://community.oracle.com/message/10631701#10631701

Upvotes: 3

int lawl is over 9000
int lawl is over 9000

Reputation: 1022

You should just execute the expensive computations in another thread and then update e.g. a progresss bar in the javafx application thread.
Also your application wont hang during the process anymore.

Like this:

Task task = new Task<Void>() { // create new task

            @Override
            public Void call() {

                // do expensive computations here

                Platform.runLater(new Runnable() { // return to application thread

                    @Override
                    public void run() {
                        // ui updates here(inside application thread)
                    }
                });
                return null;

            }
        };

        new Thread(task).start(); // execute task in new thread

Hope it helps, Laurenz.

EDIT -------------

Task<Void> task = new Task<Void>() { // create new task
            @Override
            public Void call() {

                try {
                    Thread.sleep(50); // this simulates expensive computations(in your case loading) - your app would hang for this duration
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                    // REMOVE THE SLEEP AND PUT YOUR TASK HERE

                    // Main.this.root.setPrefHeight(50); // would NOT work(because outside application thread)
                    Platform.runLater(new Runnable() { // USE THIS INSTEAD

                        @Override
                        public void run() {
                            // ui updates here(inside application thread)
                            // this is needed if you want to update your ui
                            // you cannot update any ui from outside the application thread
                        }
                    });
                    return null;

            }
        };

        new Thread(task).start(); // execute task in new thread

Upvotes: 3

Related Questions