You are currently viewing Handling Big Data with JavaFX Paginated Tables

Handling Big Data with JavaFX Paginated Tables

When developing JavaFX applications that involve handling large data sets, it’s essential to consider how to present the information to users in a user-friendly and efficient manner. One effective solution to this challenge is to implement paginated tables, where the data is divided into smaller, manageable chunks, allowing users to navigate through the content seamlessly. In this article, we’ll explore the concept of paginated tables and demonstrate how to build a JavaFX application using dynamic pagination.

What are Paginated Tables?

Paginated tables are a method of breaking down extensive data sets into smaller pages or chunks, displaying only a limited number of items per page. This approach ensures that users are not overwhelmed with information and can navigate through the data more comfortably. By providing pagination controls, users can easily switch between pages, making the application more user-friendly and responsive.

The Student Class: Our Data Model

To illustrate the implementation of paginated tables, let’s consider a simple data model representing student information. We’ll create a Student class with properties for the student’s name, age, and grade. Here’s the Student class:

public class Student {
    
    private String name;
    private int age;
    private String grade;

    public Student(String name, int age, String grade) {
        this.name = name;
        this.age = age;
        this.grade = grade;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getGrade() {
        return grade;
    }

    public void setGrade(String grade) {
        this.grade = grade;
    }

}

Implementing the PaginatedList Class

To facilitate the dynamic pagination of our data, we’ll use the PaginatedList class. This generic class takes an ObservableList and an itemsPerPage parameter, and it handles the logic for dividing the data into pages. Here’s the PaginatedList class:

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

public class PaginatedList<T> {
    
    private final ObservableList<T> data;
    private final int itemsPerPage;
    private int currentPageIndex;

    public PaginatedList(ObservableList<T> data, int itemsPerPage) {
        this.data = data;
        this.itemsPerPage = itemsPerPage;
        this.currentPageIndex = 0;
    }

    public ObservableList<T> getCurrentPageData() {
		
        int fromIndex = currentPageIndex * itemsPerPage;
        int toIndex = Math.min(fromIndex + itemsPerPage, data.size());
		
        return FXCollections.observableArrayList(data.subList(fromIndex, toIndex));
		
    }

    public int getTotalPages() {
        return (int) Math.ceil((double) data.size() / itemsPerPage);
    }

    public void setCurrentPageIndex(int pageIndex) {
        currentPageIndex = pageIndex;
    }

}

Building the JavaFX Application

With our Student class and PaginatedList in place, let’s now create the JavaFX application that showcases the paginated table. The application displays student data in a table, with each page containing a limited number of student records. We’ll also add pagination controls to enable users to navigate between pages.

import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.layout.*;
import javafx.stage.Stage;

public class Main extends Application {

    // Adjust the number of items per page as needed
    private static final int ITEMS_PER_PAGE = 10;

    private final BorderPane parent = new BorderPane();

    @Override
    public void start(Stage stage) throws Exception {
        this.setupStage(stage);
    }

    @Override
    public void init() throws Exception {
        super.init();
        this.buildUI();
    }

    private void buildUI() {

        TableView<Student> tableView = new TableView<>();

        TableColumn<Student, String> nameColumn = new TableColumn<>("Name");
        TableColumn<Student, Integer> ageColumn = new TableColumn<>("Age");
        TableColumn<Student, String> gradeColumn = new TableColumn<>("Grade");

        nameColumn.setCellValueFactory(new PropertyValueFactory<>("name"));
        ageColumn.setCellValueFactory(new PropertyValueFactory<>("age"));
        gradeColumn.setCellValueFactory(new PropertyValueFactory<>("grade"));

        tableView.getColumns().addAll(nameColumn, ageColumn, gradeColumn);

        // Replace this with your actual data list
        ObservableList<Student> data = generateDummyData();

        // Wrap the data in a paginated list
        PaginatedList<Student> paginatedData = new PaginatedList<>(data, ITEMS_PER_PAGE);

        // Set the data for the current page
        tableView.setItems(paginatedData.getCurrentPageData());

        // Set the TableView's row height to a fixed value (in pixels)
        tableView.setFixedCellSize(25);

        // Bind the preferred height of the TableView to the size of its content (rows).
        // This ensures that the TableView height adjusts dynamically based on the number of rows.
        // We add a small buffer (1.01) to provide a little extra space at the bottom.
        tableView.prefHeightProperty().bind(
          tableView.fixedCellSizeProperty().multiply(Bindings.size(tableView.getItems()).add(1.01))
        );

        // Create the Pagination control
        Pagination pagination = new Pagination(paginatedData.getTotalPages());

        // Set the maximum number of page indicators shown
        pagination.setMaxPageIndicatorCount(5);

        // Listener to update the TableView when the page changes
        pagination.currentPageIndexProperty().addListener((observable, oldValue, newValue) -> {

            paginatedData.setCurrentPageIndex(newValue.intValue());

            tableView.setItems(paginatedData.getCurrentPageData());

        });

        VBox tableViewContainer = new VBox(tableView, pagination);

        this.parent.setCenter(tableViewContainer);

    }

    private void setupStage(Stage stage) {

        Scene scene = new Scene(this.parent, 640.0, 480.0);

        // Set the stage title
        stage.setTitle("Handling Big Data with JavaFX Paginated Tables");

        // Set the stage scene
        stage.setScene(scene);

        // Center the stage on the screen
        stage.centerOnScreen();

        // Show the stage on the screen
        stage.show();

    }

    // Generate some dummy data
    private ObservableList<Student> generateDummyData() {

        ObservableList<Student> data = FXCollections.observableArrayList();

        for (int i = 1; i <= 100; i++) {

            Student student = new Student("Student " + i, i, "Grade " + i);

            data.add(student);

        }

        return data;

    }

}

Handling Big Data with JavaFX Paginated Tables

Conclusion

In this article, we delved into the concept of paginated tables in JavaFX applications. We first introduced the Student class as a simple data model to represent student information. Next, we explored the PaginatedList class, which handles the dynamic pagination of data, breaking it down into manageable pages.

Finally, we built a fully functional JavaFX application showcasing a paginated table. The application displays student data in a table and enables users to navigate between pages using the pagination controls.

With this implementation, your JavaFX applications can efficiently handle large data sets, ensuring a better user experience by presenting information in an organized and manageable manner.

I hope you found this code informative and useful. If you would like to receive more content, please consider subscribing to our newsletter!

Leave a Reply