加载窗格(GUI)时的JavaFx ProgressIndicator

加载窗格(GUI)时的JavaFx ProgressIndicator,java,user-interface,javafx,loading,Java,User Interface,Javafx,Loading,在我的应用程序中,我必须构建包含大量内容的大窗格。我将在GUI加载时显示ProgressIndicator 在我的第一个测试中,我将在向选项卡窗格中添加大量选项卡时显示ProgressIndicator 这是我的测试代码: public class SampleController implements Initializable { private TabPane tabPane; @FXML private BorderPane borderPane; Pr

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

在我的第一个测试中,我将在向选项卡窗格中添加大量选项卡时显示ProgressIndicator

这是我的测试代码:

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();
    }
}
公共类SampleController实现可初始化{
私有选项卡窗格选项卡窗格;
@FXML
私有边框窗格边框窗格;
进程指示器myProgressIndicator;
任务长任务;
@凌驾
公共void初始化(URL位置、ResourceBundle资源)
{
myProgressIndicator=新的ProgressIndicator();
窗格p1=新窗格(myProgressIndicator);
tabPane=新tabPane();
窗格p2=新窗格(选项卡窗格);
myLongTask=新任务()
{
@凌驾
受保护的Void调用()引发异常
{
对于(int i=1;i<1000;i++)
{
//睡眠(10);
Tab newTab=新选项卡(“编号:+i”);
tabPane.getTabs().add(newTab);
}
返回null;
}
};
borderPane.centerProperty().bind(Bindings.when(myLongTask.runningProperty())。然后(p1)。否则(p2));
新线程(myLongTask).start();
}
}
但是如果任务已经完成,应用程序将显示窗口。如果我用
Thread.sleep(10)
替换for循环中的行,应用程序将显示指示器,毕竟,sleep将显示GUI


当GUI尚未加载时,如何显示指示器?

您有一个创建结果的
任务(即
选项卡窗格
)。因此,使用
TabPane
作为类型参数比使用
Void
更方便,您还应该调用以更新并将该属性绑定到

可以将结果添加到中的
边框窗格
,而不是创建(或多或少)复杂的绑定:

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

您有一个创建结果的
任务
(即
选项卡窗格
)。因此,使用
TabPane
作为类型参数比使用
Void
更方便,您还应该调用以更新并将该属性绑定到

可以将结果添加到中的
边框窗格
,而不是创建(或多或少)复杂的绑定:

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

我把班级改成这样:

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));
    });
}
公共类SampleController实现可初始化{
@FXML
私有边框窗格边框窗格;
进程指示器myProgressIndicator;
任务长任务;
TabPane TabPane=新建TabPane();
@凌驾
公共void初始化(URL位置、ResourceBundle资源)
{
myLongTask=新任务()
{
@凌驾
受保护的列表调用()引发异常
{
List newTabs=newarraylist();
最终整数计数=1000-1;
对于(int i=1;i{
最终列表结果=myLongTask.getValue();
最后一步=5;
最终整数大小=result.size();
AnimationTimer=新的AnimationTimer(){
int指数=0;
@凌驾
公共无效句柄(长){
tabPane.getTabs().addAll(result.subList(index,Math.min(size,index+step));
指数+=步长;
如果(索引>=大小){
这个。停止();
}
}
};
timer.start();
设置中心(新窗格(选项卡窗格));
});
}
}


这就是你的意思吗?

我把课堂改成这样:

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));
    });
}
公共类SampleController实现可初始化{
@FXML
私有边框窗格边框窗格;
进程指示器myProgressIndicator;
任务长任务;
TabPane TabPane=新建TabPane();
@凌驾
公共void初始化(URL位置、ResourceBundle资源)
{
myLongTask=新任务()
{
@凌驾
受保护的列表调用()引发异常
{
List newTabs=newarraylist();
最终整数计数=1000-1;
对于(int i=1;i{
最终列表结果=myLongTask.getValue();
最后一步=5;
最终整数大小=result.size();
AnimationTimer=新的AnimationTimer(){
int指数=0;
@凌驾
公共无效句柄(长){
tabPane.getTabs().addAll(result.subList(index,Math.min(size,index+step));
指数+=步长;
如果(索引>=大小){
这个。停止();
}
}
};
timer.start();
设置中心(新窗格(选项卡窗格));
});
}
}


这就是你的意思吗?

tabPane.getTabs().add(newTab);
是在后台线程上修改用户界面,这是不允许的(请参见,例如,
tabPane.getTabs().add(newTab);
是在后台线程上修改用户界面,这是不允许的(请参见,例如“线程化”)@kayf:创建999
选项卡
s很快;使用999
选项卡
s布局
选项卡
则不快。在布局过程中,您的UI将冻结。(请参阅答案更新)@kayf:创建999
选项卡
s很快;使用999
选项卡
s布局
选项卡窗格
则不然。在布局过程中,您的UI将冻结。(请参阅答案更新)