JavaFx ProgressIndicator while Loading Pane (GUI)

后端 未结 2 546
我寻月下人不归
我寻月下人不归 2021-01-17 00:56

In my application, I have to build big panes with a lot of content. I will show a ProgressIndicator while the GUI is loading.

My first test, I will show a ProgressIn

相关标签:
2条回答
  • 2021-01-17 01:30

    You have a Task that creates a result (i.e. a TabPane). Therefore it's more convenient to use TabPane as type parameter instead of Void also you should call updateProgress to update the progress property and bind that property to the progress property of the ProgressIndicator.

    The result can be added to the BorderPane in the onSucceded handler instead of creating a (more or less) complicated binding:

    Task<TabPane> myLongTask;
    
    @Override
    public void initialize(URL url, ResourceBundle rb) {
    
        myLongTask = new Task<TabPane>() {
    
            @Override
            protected TabPane call() throws Exception {
                TabPane tabPane = new TabPane();
                List<Tab> tabs = tabPane.getTabs();
                final int count = 1000 - 1;
                for (int i = 1; i <= count; i++) {
                    Thread.sleep(10);
                    Tab newTab = new Tab("Number:" + i);
                    tabs.add(newTab);
                    updateProgress(i, count);
                }
                return tabPane;
            }
        };
        myLongTask.setOnSucceeded(evt -> {
            // update ui with results
            tabPane = myLongTask.getValue();
            borderPane.setCenter(new Pane(tabPane));
        });
        
        // add progress indicator to show progress of myLongTask
        myProgressIndicator = new ProgressIndicator();
        myProgressIndicator.progressProperty().bind(myLongTask.progressProperty());
        borderPane.setCenter(new Pane(myProgressIndicator));
    
        new Thread(myLongTask).start();
    }
    

    Simply creating the tabs is fast however, and you won't see any progress indicator in the UI. Layouting a TabPane with 999 Tabs however is rather slow. The UI will most likely freeze for a short time. You can work around this by adding only a limited number of Tabs in each frame:

    Return a List<Tab> from the task instead of a TabPane; these Tabs should not be added to the TabPane (yet). You can use a AnimationTimer to add a fixed number of tabs each frame:

    final List<Tab> result = ...; // your tab list
    
    // number of elements added each frame
    final int step = 5;
    
    final int size = result.size();
    AnimationTimer timer = new AnimationTimer() {
    
        int index = 0;
                
        @Override
        public void handle(long now) {
            tabPane.getTabs().addAll(result.subList(index, Math.min(size, index+step)));
            index += step;
            if (index >= size) {
                this.stop();
            }
        }
    };
    timer.start();
    
    0 讨论(0)
  • 2021-01-17 01:35

    I have change the class like this:

    public class SampleController implements Initializable {
    @FXML
    private BorderPane borderPane;
    ProgressIndicator myProgressIndicator;
    Task<List<Tab>> myLongTask;
    TabPane tabPane = new TabPane();
    
    @Override
    public void initialize(URL location, ResourceBundle resources)
    {
            myLongTask = new Task<List<Tab>>()
            {
                @Override
                protected List<Tab> call() throws Exception
                {
                List<Tab> newTabs = new ArrayList<Tab>();
                final int count = 1000 - 1;
                for (int i = 1; i <= count; i++)
                {
                    Tab newTab = new Tab("Number:" + i);
                    newTabs.add(newTab);
                }
                return newTabs;
                }
            };
    
        myProgressIndicator = new ProgressIndicator();
        myProgressIndicator.progressProperty().bind(myLongTask.progressProperty());
        borderPane.setCenter(new Pane(myProgressIndicator));
    
        new Thread(myLongTask).start();
    
        myLongTask.setOnSucceeded(evt -> {
        final List<Tab> result = myLongTask.getValue();
        final int step = 5;
        final int size = result.size();
    
        AnimationTimer timer = new AnimationTimer() {
            int index = 0;
            @Override
            public void handle(long now) {
            tabPane.getTabs().addAll(result.subList(index, Math.min(size, index+step)));
            index += step;
            if (index >= size) {
                this.stop();
            }
            }
        };
            timer.start();
            borderPane.setCenter(new Pane(tabPane));
        });
    }
    

    }

    Is it this what you mean?

    0 讨论(0)
提交回复
热议问题