在 JavaFX table 分页中添加进度条
Add progress bar in JavaFX table pagination
我有这个JavaFX的例子table。
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MainApp extends Application
{
private final static int dataSize = 10_023;
private final static int rowsPerPage = 1000;
private final TableView<Sample> table = createTable();
private final List<Sample> data = createData();
private List<Sample> createData()
{
List<Sample> data = new ArrayList<>(dataSize);
for (int i = 0; i < dataSize; i++)
{
data.add(new Sample(i, "foo " + i, "bar " + i));
}
return data;
}
private TableView<Sample> createTable()
{
TableView<Sample> table = new TableView<>();
TableColumn<Sample, Integer> column1 = new TableColumn<>("Id");
column1.setCellValueFactory(param -> param.getValue().id);
column1.setPrefWidth(150);
TableColumn<Sample, String> column2 = new TableColumn<>("Foo");
column2.setCellValueFactory(param -> param.getValue().foo);
column2.setPrefWidth(250);
TableColumn<Sample, String> column3 = new TableColumn<>("Bar");
column3.setCellValueFactory(param -> param.getValue().bar);
column3.setPrefWidth(250);
table.getColumns().addAll(column1, column2, column3);
return table;
}
private Node createPage(int pageIndex)
{
int fromIndex = pageIndex * rowsPerPage;
int toIndex = Math.min(fromIndex + rowsPerPage, data.size());
table.setItems(FXCollections.observableArrayList(data.subList(fromIndex, toIndex)));
return new BorderPane(table);
}
@Override
public void start(final Stage stage) throws Exception
{
Pagination pagination = new Pagination((data.size() / rowsPerPage + 1), 0);
pagination.setPageFactory(this::createPage);
Scene scene = new Scene(new BorderPane(pagination), 1024, 768);
stage.setScene(scene);
stage.setTitle("Table pager");
stage.show();
}
public static void main(String[] args) throws Exception
{
launch(args);
}
public static class Sample
{
private final ObservableValue<Integer> id;
private final SimpleStringProperty foo;
private final SimpleStringProperty bar;
private Sample(int id, String foo, String bar)
{
this.id = new SimpleObjectProperty<>(id);
this.foo = new SimpleStringProperty(foo);
this.bar = new SimpleStringProperty(bar);
}
}
}
有没有办法在页面切换和加载数据时添加进度条?
我不太清楚如何在加载数据时使用进度指示器。
有什么有用的例子吗?
可能最简单的解决方案是重写 createPage(int)
方法:
- 替换placeholder of the
TableView
with a ProgressIndicator
.
- 创建一个
Task
来计算下一页的内容(在我的例子中只是一个虚拟人在做 Thread.sleep()
)。
- 当
Task
完成后,将占位符替换为旧的(备份和恢复)并将数据设置为 TableView
。
这是 createPage()
方法的一个小例子:
private Node createPage(int pageIndex) {
Node oldPlaceHolder = table.getPlaceholder();
ProgressIndicator progress = new ProgressIndicator();
progress.setMaxSize(90, 90);
table.setPlaceholder(new StackPane(progress));
table.getItems().clear();
Task<ObservableList<Sample>> task = new Task<ObservableList<Sample>>() {
@Override
protected ObservableList<Sample> call() throws Exception {
for(int i = 0; i < 99; i++)
{
Thread.sleep(20);
updateProgress(i, 100);
}
int fromIndex = pageIndex * rowsPerPage;
int toIndex = Math.min(fromIndex + rowsPerPage, data.size());
return (FXCollections.observableArrayList(data.subList(
fromIndex, toIndex)));
}
};
progress.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(ev -> {
table.setItems(task.getValue());
table.setPlaceholder(oldPlaceHolder);
});
new Thread(task).start();
return new BorderPane(table);
}
您可以将 table 放入 StackPane 并在其顶部放置一个进度指示器。
这是一个例子:
public class TableWithProgressIndicator extends Application {
private final static int dataSize = 10_023;
private final static int rowsPerPage = 1000;
private ObservableList<Sample> dataList = FXCollections.observableArrayList(new ArrayList<Sample>(rowsPerPage));
private TableView<Sample> table = null;
StackPane tablePane = new StackPane();
ProgressIndicator progressIndicator = new ProgressIndicator();
private List<Sample> loadData(int fromIndex, int toIndex) {
List<Sample> list = new ArrayList<>();
try {
for (int i = fromIndex; i < toIndex; i++) {
list.add(new Sample(i, "foo " + i, "bar " + i));
}
Thread.sleep(2000);
} catch( Exception e) {
e.printStackTrace();
}
return list;
}
@Override
public void start(final Stage stage) throws Exception {
table = createTable( dataList);
Pagination pagination = new Pagination((dataSize / rowsPerPage + 1), 0);
progressIndicator.setMaxSize(200, 200);
// wrap table and progress indicator into a stackpane, progress indicator is on top of table
tablePane.getChildren().add(table);
tablePane.getChildren().add(progressIndicator);
pagination.setPageFactory(new Callback<Integer, Node>() {
public Node call(final Integer pageIndex) {
progressIndicator.setVisible(true);
dataList.clear();
// long running background task
new Thread() {
public void run() {
try {
int fromIndex = pageIndex * rowsPerPage;
int toIndex = Math.min(fromIndex + rowsPerPage, dataSize);
List<Sample> loadedList = loadData(fromIndex, toIndex);
Platform.runLater(() -> dataList.setAll( loadedList));
} finally {
Platform.runLater(() -> progressIndicator.setVisible(false));
}
}
}.start();
return tablePane;
}
});
Scene scene = new Scene(new BorderPane(pagination), 1024, 768);
stage.setScene(scene);
stage.setTitle("Table pager");
stage.show();
}
private TableView<Sample> createTable( ObservableList<Sample> data) {
TableView<Sample> table = new TableView<>();
TableColumn<Sample, Integer> column1 = new TableColumn<>("Id");
column1.setCellValueFactory(param -> param.getValue().id);
column1.setPrefWidth(150);
TableColumn<Sample, String> column2 = new TableColumn<>("Foo");
column2.setCellValueFactory(param -> param.getValue().foo);
column2.setPrefWidth(250);
TableColumn<Sample, String> column3 = new TableColumn<>("Bar");
column3.setCellValueFactory(param -> param.getValue().bar);
column3.setPrefWidth(250);
table.getColumns().addAll(column1, column2, column3);
table.setItems( data);
table.setPlaceholder(new Label(""));
return table;
}
public static void main(String[] args) throws Exception {
launch(args);
}
public static class Sample {
private final ObservableValue<Integer> id;
private final SimpleStringProperty foo;
private final SimpleStringProperty bar;
private Sample(int id, String foo, String bar) {
this.id = new SimpleObjectProperty<>(id);
this.foo = new SimpleStringProperty(foo);
this.bar = new SimpleStringProperty(bar);
}
}
}
我有这个JavaFX的例子table。
import java.util.ArrayList;
import java.util.List;
import javafx.application.Application;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Pagination;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
public class MainApp extends Application
{
private final static int dataSize = 10_023;
private final static int rowsPerPage = 1000;
private final TableView<Sample> table = createTable();
private final List<Sample> data = createData();
private List<Sample> createData()
{
List<Sample> data = new ArrayList<>(dataSize);
for (int i = 0; i < dataSize; i++)
{
data.add(new Sample(i, "foo " + i, "bar " + i));
}
return data;
}
private TableView<Sample> createTable()
{
TableView<Sample> table = new TableView<>();
TableColumn<Sample, Integer> column1 = new TableColumn<>("Id");
column1.setCellValueFactory(param -> param.getValue().id);
column1.setPrefWidth(150);
TableColumn<Sample, String> column2 = new TableColumn<>("Foo");
column2.setCellValueFactory(param -> param.getValue().foo);
column2.setPrefWidth(250);
TableColumn<Sample, String> column3 = new TableColumn<>("Bar");
column3.setCellValueFactory(param -> param.getValue().bar);
column3.setPrefWidth(250);
table.getColumns().addAll(column1, column2, column3);
return table;
}
private Node createPage(int pageIndex)
{
int fromIndex = pageIndex * rowsPerPage;
int toIndex = Math.min(fromIndex + rowsPerPage, data.size());
table.setItems(FXCollections.observableArrayList(data.subList(fromIndex, toIndex)));
return new BorderPane(table);
}
@Override
public void start(final Stage stage) throws Exception
{
Pagination pagination = new Pagination((data.size() / rowsPerPage + 1), 0);
pagination.setPageFactory(this::createPage);
Scene scene = new Scene(new BorderPane(pagination), 1024, 768);
stage.setScene(scene);
stage.setTitle("Table pager");
stage.show();
}
public static void main(String[] args) throws Exception
{
launch(args);
}
public static class Sample
{
private final ObservableValue<Integer> id;
private final SimpleStringProperty foo;
private final SimpleStringProperty bar;
private Sample(int id, String foo, String bar)
{
this.id = new SimpleObjectProperty<>(id);
this.foo = new SimpleStringProperty(foo);
this.bar = new SimpleStringProperty(bar);
}
}
}
有没有办法在页面切换和加载数据时添加进度条?
我不太清楚如何在加载数据时使用进度指示器。
有什么有用的例子吗?
可能最简单的解决方案是重写 createPage(int)
方法:
- 替换placeholder of the
TableView
with aProgressIndicator
. - 创建一个
Task
来计算下一页的内容(在我的例子中只是一个虚拟人在做Thread.sleep()
)。 - 当
Task
完成后,将占位符替换为旧的(备份和恢复)并将数据设置为TableView
。
这是 createPage()
方法的一个小例子:
private Node createPage(int pageIndex) {
Node oldPlaceHolder = table.getPlaceholder();
ProgressIndicator progress = new ProgressIndicator();
progress.setMaxSize(90, 90);
table.setPlaceholder(new StackPane(progress));
table.getItems().clear();
Task<ObservableList<Sample>> task = new Task<ObservableList<Sample>>() {
@Override
protected ObservableList<Sample> call() throws Exception {
for(int i = 0; i < 99; i++)
{
Thread.sleep(20);
updateProgress(i, 100);
}
int fromIndex = pageIndex * rowsPerPage;
int toIndex = Math.min(fromIndex + rowsPerPage, data.size());
return (FXCollections.observableArrayList(data.subList(
fromIndex, toIndex)));
}
};
progress.progressProperty().bind(task.progressProperty());
task.setOnSucceeded(ev -> {
table.setItems(task.getValue());
table.setPlaceholder(oldPlaceHolder);
});
new Thread(task).start();
return new BorderPane(table);
}
您可以将 table 放入 StackPane 并在其顶部放置一个进度指示器。
这是一个例子:
public class TableWithProgressIndicator extends Application {
private final static int dataSize = 10_023;
private final static int rowsPerPage = 1000;
private ObservableList<Sample> dataList = FXCollections.observableArrayList(new ArrayList<Sample>(rowsPerPage));
private TableView<Sample> table = null;
StackPane tablePane = new StackPane();
ProgressIndicator progressIndicator = new ProgressIndicator();
private List<Sample> loadData(int fromIndex, int toIndex) {
List<Sample> list = new ArrayList<>();
try {
for (int i = fromIndex; i < toIndex; i++) {
list.add(new Sample(i, "foo " + i, "bar " + i));
}
Thread.sleep(2000);
} catch( Exception e) {
e.printStackTrace();
}
return list;
}
@Override
public void start(final Stage stage) throws Exception {
table = createTable( dataList);
Pagination pagination = new Pagination((dataSize / rowsPerPage + 1), 0);
progressIndicator.setMaxSize(200, 200);
// wrap table and progress indicator into a stackpane, progress indicator is on top of table
tablePane.getChildren().add(table);
tablePane.getChildren().add(progressIndicator);
pagination.setPageFactory(new Callback<Integer, Node>() {
public Node call(final Integer pageIndex) {
progressIndicator.setVisible(true);
dataList.clear();
// long running background task
new Thread() {
public void run() {
try {
int fromIndex = pageIndex * rowsPerPage;
int toIndex = Math.min(fromIndex + rowsPerPage, dataSize);
List<Sample> loadedList = loadData(fromIndex, toIndex);
Platform.runLater(() -> dataList.setAll( loadedList));
} finally {
Platform.runLater(() -> progressIndicator.setVisible(false));
}
}
}.start();
return tablePane;
}
});
Scene scene = new Scene(new BorderPane(pagination), 1024, 768);
stage.setScene(scene);
stage.setTitle("Table pager");
stage.show();
}
private TableView<Sample> createTable( ObservableList<Sample> data) {
TableView<Sample> table = new TableView<>();
TableColumn<Sample, Integer> column1 = new TableColumn<>("Id");
column1.setCellValueFactory(param -> param.getValue().id);
column1.setPrefWidth(150);
TableColumn<Sample, String> column2 = new TableColumn<>("Foo");
column2.setCellValueFactory(param -> param.getValue().foo);
column2.setPrefWidth(250);
TableColumn<Sample, String> column3 = new TableColumn<>("Bar");
column3.setCellValueFactory(param -> param.getValue().bar);
column3.setPrefWidth(250);
table.getColumns().addAll(column1, column2, column3);
table.setItems( data);
table.setPlaceholder(new Label(""));
return table;
}
public static void main(String[] args) throws Exception {
launch(args);
}
public static class Sample {
private final ObservableValue<Integer> id;
private final SimpleStringProperty foo;
private final SimpleStringProperty bar;
private Sample(int id, String foo, String bar) {
this.id = new SimpleObjectProperty<>(id);
this.foo = new SimpleStringProperty(foo);
this.bar = new SimpleStringProperty(bar);
}
}
}