在JavaFX表分页中添加进度条

时间:2015-01-28 14:21:47

标签: javafx javafx-2 javafx-8

我有JavaFX表的这个例子。

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

有没有办法在切换页面和加载数据时添加进度条?

在加载数据时如何使用进度指示器并不是很清楚。

有没有有用的例子?

2 个答案:

答案 0 :(得分:2)

最简单的解决方案可能是重写createPage(int)方法:

  1. TableView的{​​{3}}替换为placeholder
  2. 创建一个ProgressIndicator,用于计算下一页的内容(在我的示例中只是一个虚拟的Thread.sleep())。
  3. 完成Task后,将占位符替换为旧版本(备份和恢复),并将数据设置为TableView
  4. 这是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);
    }
    

答案 1 :(得分:1)

您可以将表格放入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);
        }
    }
}