加载期间显示消息

时间:2014-02-22 10:13:53

标签: java javafx javafx-2 javafx-8

我有一个带TabPane的JavaFX,它将带有数据的Java对象保存到不同的选项卡中。我发现当选项卡的内容需要时间加载时,因为有SQL查询要执行,应用程序才会挂起。在内容使用期间有没有办法显示一些“正在加载”的消息?例如:

Tab.setContent(<some_heavy_Java_Object>);

在JavaFX或Java中有解决方法吗?

P.S我测试了这段代码示例,但是当我尝试运行代码时出现错误:

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);

你能帮我解决这个问题。

解决问题的另一种尝试:

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);

这次结果为空。

又一次失败的尝试。

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);

2 个答案:

答案 0 :(得分:3)

你应该只在另一个线程中执行昂贵的计算然后更新,例如javafx应用程序线程中的进度条 此外,您的应用程序将不再在此过程中挂起。

像这样:

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

希望它有所帮助,Laurenz。

编辑-------------

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

答案 1 :(得分:3)

你必须在不同的任务线程中加载数据,我看到你正在尝试做同样的事情。代码的问题在于您没有更新进度条。您必须使用updateProgress,如此处所示

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

以下是来自Jewelsea的一个非常好的示例,他非常好地展示了Task的使用以及如何使用它来更新UI上的进度

Update progress bar and multiple labels from thread

在这里,您可以了解如何使用任务以及从任务

更新UI

更好的例子是

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

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