加载窗格(GUI)时的JavaFx ProgressIndicator

时间:2016-01-29 09:30:53

标签: java user-interface javafx loading

在我的应用程序中,我必须构建包含大量内容的大窗格。我将在GUI加载时显示ProgressIndicator。

我的第一次测试,我将在TabPane中添加大量标签时显示ProgressIndicator。

那是我的测试代码:

{Binding Path=DataContext.Command1, ElementName=MyItemsControl}

但是,如果任务完成,应用程序将显示窗口。如果我用for public class SampleController implements Initializable { private TabPane tabPane; @FXML private BorderPane borderPane; ProgressIndicator myProgressIndicator; Task<Void> myLongTask; @Override public void initialize(URL location, ResourceBundle resources) { myProgressIndicator = new ProgressIndicator(); Pane p1 = new Pane(myProgressIndicator); tabPane = new TabPane(); Pane p2 = new Pane(tabPane); myLongTask = new Task<Void>() { @Override protected Void call() throws Exception { for (int i = 1; i < 1000; i++) { // Thread.sleep(10); Tab newTab = new Tab("Number:" + i); tabPane.getTabs().add(newTab); } return null; } }; borderPane.centerProperty().bind(Bindings.when(myLongTask.runningProperty()).then(p1).otherwise(p2)); new Thread(myLongTask).start(); } } 替换for循环中的行,应用程序会显示指示符,然后睡眠,它会显示GUI。

如果尚未加载GUI,如何显示指示符?

2 个答案:

答案 0 :(得分:2)

您有Task创建结果(即TabPane)。因此,使用TabPane作为类型参数而非Void更方便您也应该调用updateProgress来更新progress property并将该属性绑定到{{3} }}

可以将结果添加到the progress property of the ProgressIndicator中的BorderPane,而不是创建(或多或少)复杂的绑定:

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

然而,简单地创建选项卡很快,并且您在UI中看不到任何进度指示器。然而,使用999 TabPane来布置Tabs相当慢。用户界面很可能会在很短的时间内冻结。您可以通过在每个帧中仅添加有限数量的Tab来解决此问题:

从任务中返回List<Tab>而不是TabPane;这些Tab不应添加到TabPane(尚未)。您可以使用AnimationTimer每帧添加固定数量的标签:

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

答案 1 :(得分:0)

我改变了这样的课程:

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

}

这是你的意思吗?