Панель прокрутки в javafx - это нагрузка на оперативную память при отображении большой коллекции элементов и представлений. - PullRequest
0 голосов
/ 29 декабря 2018

Я разрабатываю библиотечное приложение с использованием javafx, где пользователь может импортировать файлы epub, и он получает библиотеку с полками, где каждая полка содержит не более 6 книг.Я использую область прокрутки внутри нее, VBox, содержащий дополнительные VBox (каждый напоминает полку), каждый из которых содержит изображение (которое является полкой), а над ним HBox, содержащий изображения обложек книг.Я попытался с представлением списка, но он не работает, так как в представлении списка отображается список элементов, по которым вы щелкаете один из них, и в моем случае элемент будет представлять собой целую полку, содержащую несколько книг (я хочу обработать щелчок покаждая книга в отдельности).Извините за длинное описание. Это изображение моей работы

1 Ответ

0 голосов
/ 29 декабря 2018

Есть много вариантов для этого;но, вероятно, лучше всего использовать ListView, как предлагают комментарии.

Пример приложения ниже продемонстрирует один из способов сделать это.Однако я не сделал никакой работы по стилю ListView.Главным образом потому, что я сам не очень хорошо разбираюсь в CSS (я приветствую правки и предложения), а также потому, что это выходит за рамки этого довольно расплывчатого вопроса.

Объединение ListView с пользовательским CellFactoryвы можете создать макет для каждой "полки" в вашей библиотеке;ListView будет отображать каждую строку с использованием этого макета.

В приведенном ниже коде имеются дополнительные комментарии.

Пример библиотеки MCVE:

LibraryExample.java:

import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.geometry.Insets;
import javafx.geometry.Orientation;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.control.Separator;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
import javafx.util.Callback;

import java.util.List;

public class LibraryExample extends Application {

    // Our list of shelves that will be displayed in the ListView
    private final ObservableList<Shelf> shelves = FXCollections.observableArrayList();

    public static void main(String[] args) {
        launch(args);
    }

    @Override
    public void start(Stage primaryStage) {

        // Simple interface
        VBox root = new VBox(5);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        // Build a list of 100 sample books. This list could come from a database or other outside source, of course
        List<Book> books = FXCollections.observableArrayList();
        for (int i = 0; i < 100; i++) {
            books.add(new Book("Book #" + i, new ImageView("sample/generic-cover.png")));
        }

        // We will now create our shelves for the books. We will limit the number of books to 6 per shelf. This uses
        // the subList method of our List to grab every 6 books until we run out.
        int index = 0;
        while (index < books.size()) {

            // Make sure there are at least 6 books remaining, otherwise, we need to get the subList up to the size of
            // the original list.
            final int numToAdd = (index + 6 <= books.size() ? index + 6 : books.size());
            shelves.addAll(new Shelf(books.subList(index, numToAdd)));
            index += 6;
        }

        // Now, let's create our ListView that will hold our shelves.
        ListView<Shelf> listView = new ListView<>();
        VBox.setVgrow(listView, Priority.ALWAYS);

        // Now for the magic. We will override the CellFactory for the ListView so we can provide our own layout
        // for each row
        listView.setCellFactory(new Callback<ListView<Shelf>, ListCell<Shelf>>() {
            @Override
            public ListCell<Shelf> call(ListView<Shelf> param) {
                return new ShelfListCell();
            }
        });

        listView.setItems(shelves);

        root.getChildren().add(listView);

        // Show the Stage
        primaryStage.setWidth(700);
        primaryStage.setHeight(600);
        primaryStage.setScene(new Scene(root));
        primaryStage.show();
    }
}

class ShelfListCell extends ListCell<Shelf> {

    @Override
    protected void updateItem(Shelf shelf, boolean empty) {
        super.updateItem(shelf, empty);

        if (shelf == null || empty) {
            setGraphic(null);
        } else {

            // Here, we will build our layout for each shelf
            VBox root = new VBox(5);
            root.setAlignment(Pos.CENTER);
            root.setPadding(new Insets(5));

            HBox hBox = new HBox(20);
            hBox.setAlignment(Pos.CENTER);
            hBox.setPadding(new Insets(5));

            // Add image for each each book on this shelf to the layout
            for (Book book : shelf.getBooks()) {

                // Get the image of the book and add a simple click listener
                ImageView cover = book.getCoverImage();
                cover.setPreserveRatio(true);
                cover.setFitHeight(100);
                cover.setOnMouseClicked(event -> System.out.println("Clicked " + book.getTitle()));

                hBox.getChildren().add(book.getCoverImage());
            }

            root.getChildren().addAll(hBox, new Separator(Orientation.HORIZONTAL));

            // Set the cell to display our layout
            setGraphic(root);

        }
    }
}

Book.java:

import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty;
import javafx.beans.property.SimpleStringProperty;
import javafx.beans.property.StringProperty;
import javafx.scene.image.ImageView;

public class Book {

    private final StringProperty title = new SimpleStringProperty();
    private final ObjectProperty<ImageView> coverImage = new SimpleObjectProperty<>();

    public Book(String title, ImageView coverImage) {
        this.title.set(title);
        this.coverImage.set(coverImage);
    }

    public String getTitle() {
        return title.get();
    }

    public StringProperty titleProperty() {
        return title;
    }

    public void setTitle(String title) {
        this.title.set(title);
    }

    public ImageView getCoverImage() {
        return coverImage.get();
    }

    public ObjectProperty<ImageView> coverImageProperty() {
        return coverImage;
    }

    public void setCoverImage(ImageView coverImage) {
        this.coverImage.set(coverImage);
    }
}

Shelf.java:

import javafx.beans.property.ListProperty;
import javafx.beans.property.SimpleListProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import java.util.List;

public class Shelf {

    // Set max number of books per shelf
    private final static int MAX_BOOKS = 6;

    // Our observable list of books
    private final ListProperty<Book> books = new SimpleListProperty<>(FXCollections.observableArrayList());

    public Shelf(List<Book> books) {
        this.books.addAll(books);
    }

    public void addBooks(Book... books) {
        this.books.addAll(books);
    }

    public static int getMaxBooks() {
        return MAX_BOOKS;
    }

    public ObservableList<Book> getBooks() {
        return books.get();
    }

    public ListProperty<Book> booksProperty() {
        return books;
    }

    public void setBooks(ObservableList<Book> books) {
        this.books.set(books);
    }
}

Результат:

screenshot

...