在我的应用程序中,我必须构建包含大量内容的大 Pane 。当 GUI 加载时,我将显示一个 ProgressIndicator。
我的第一个测试,我将在向 TabPane 添加大量选项卡时显示 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();
}
}
但是如果任务完成,应用程序将显示该窗口。如果我用 Thread.sleep(10) 替换 for 循环内的行,应用程序将显示指示器,并且在 sleep 之后,它会显示 GUI。
如何在 GUI 尚未加载时显示指示器?
最佳答案
您有一个Task
创建一个结果(即 TabPane
)。因此使用TabPane
更加方便作为类型参数而不是 Void
您也应该调用 updateProgress
更新 progress
property并将该属性绑定(bind)到 the progress
property of the ProgressIndicator
.
结果可以添加到 BorderPane
在 onSucceded
handler而不是创建(或多或少)复杂的绑定(bind):
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
999 Tabs
但是速度相当慢。用户界面很可能会短暂卡住。您可以通过仅添加有限数量的 Tab
来解决此问题。每帧中的 s:
返回List<Tab>
来自任务而不是 TabPane
;这些Tab
s 不应添加到 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();
关于加载 Pane 时的 JavaFx ProgressIndicator (GUI),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35081031/