加载窗格(GUI)时的JavaFx ProgressIndicator
在我的应用程序中,我必须构建包含大量内容的大窗格。我将在GUI加载时显示ProgressIndicator 在我的第一个测试中,我将在向选项卡窗格中添加大量选项卡时显示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
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将冻结。(请参阅答案更新)