Код: Выделить всё
public class PdfDocumentModel {
private final PDDocument document;
private float dpi = 110;
// Constructor accepts InputStream
public PdfDocumentModel(InputStream inputStream) throws IOException {
this.document = PDDocument.load(inputStream); // Load PDF from InputStream
}
public int getPageCount() {
return document.getNumberOfPages();
}
public void close() throws IOException {
document.close();
}
public void setDpi(float dpi) {
this.dpi = dpi; // Allow setting DPI dynamically for rendering
}
// Render page to temporary file with dynamic DPI control
public synchronized File renderPageToTempFile(int pageIndex) throws IOException {
if (pageIndex < 0 || pageIndex >= getPageCount()) {
throw new IndexOutOfBoundsException("Invalid page index: " + pageIndex);
}
// Render the page to a BufferedImage with the current DPI setting
PDFRenderer renderer = new PDFRenderer(document);
BufferedImage image = renderer.renderImageWithDPI(pageIndex, dpi); // Use dynamic DPI
// Convert BufferedImage to temporary PNG file
Path tempFilePath = Files.createTempFile("page_" + pageIndex + "_", ".png");
File tempFile = tempFilePath.toFile();
try (OutputStream outputStream = Files.newOutputStream(tempFile.toPath())) {
ImageIO.write(image, "PNG", outputStream);
}
return tempFile;
}
public void deleteTempFile(File tempFile) {
if (tempFile != null && tempFile.exists()) {
boolean deleted = tempFile.delete();
if (!deleted) {
System.err.println("Failed to delete temporary file: " + tempFile.getAbsolutePath());
}
}
}
}
Код: Выделить всё
This is my View model:
Код: Выделить всё
public class CenterViewModel {
private PdfDocumentModel pdfDocument;
private final ListProperty pages = new SimpleListProperty(FXCollections.observableArrayList());
private final IntegerProperty currentPage = new SimpleIntegerProperty();
private final ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
public CenterViewModel() {
currentPage.addListener((obs, oldPage, newPage) -> {
if (newPage.intValue() >= 0 && newPage.intValue() < pages.size()) {
loadPage(newPage.intValue());
}
});
}
public void loadPdf(InputStream inputStream) throws IOException {
// Close the existing PDF document if one is already loaded
if (pdfDocument != null) {
closePdf();
}
// Create a new PdfDocumentModel using the InputStream
pdfDocument = new PdfDocumentModel(inputStream);
// Clear previous page list and prepare for new pages
pages.clear();
int pageCount = pdfDocument.getPageCount();
// Add placeholders for each page
for (int i = 0; i < pageCount; i++) {
pages.add(null); // Placeholder for each page
}
// Load a subset of pages initially (e.g., first 100 pages)
loadPages(0, Math.min(pageCount, 2000));
}
public void setDpi(float dpi) {
pdfDocument.setDpi(dpi);
}
public void loadPages(int startIndex, int endIndex) {
for (int i = startIndex; i < endIndex; i++) {
if (i >= pages.size() || pages.get(i) != null) {
continue;
}
loadPage(i);
}
}
public void loadPage(int pageIndex) {
if (pageIndex < 0 || pageIndex >= pages.size()) {
throw new IndexOutOfBoundsException("Invalid page index: " + pageIndex);
}
// Render page asynchronously
Task task = new Task() {
@Override
protected File call() throws Exception {
return pdfDocument.renderPageToTempFile(pageIndex);
}
@Override
protected void succeeded() {
File tempFile = getValue();
try {
BufferedImage image = ImageIO.read(tempFile);
pages.set(pageIndex, image); // Update page image
pdfDocument.deleteTempFile(tempFile); // Clean up temporary file
} catch (IOException e) {
System.err.println("Failed to read page " + pageIndex + ": " + e.getMessage());
}
}
@Override
protected void failed() {
System.err.println("Failed to render page " + pageIndex + ": " + getException().getMessage());
}
};
executorService.submit(task);
}
public void shutdownExecutor() {
if (!executorService.isShutdown()) {
executorService.shutdown();
}
}
public int getTotalPages() {
return pdfDocument != null ? pdfDocument.getPageCount() : 0;
}
public ListProperty pagesProperty() {
return pages;
}
public IntegerProperty currentPageProperty() {
return currentPage;
}
public void setCurrentPage(int pageIndex) {
if (pageIndex >= 0 && pageIndex < pages.size()) {
currentPage.set(pageIndex);
}
}
public void closePdf() throws IOException {
if (pdfDocument != null) {
pdfDocument.close();
}
pages.clear();
}
}
Код: Выделить всё
public class CenterView {
private final ListView listView;
private final ListProperty pages = new SimpleListProperty(FXCollections.observableArrayList());
private final CenterViewModel centerViewModel = new CenterViewModel();
private final IntegerProperty currentPage = new SimpleIntegerProperty();
private final Label totalPagesLabel = new Label();
private final Button resetButton = new Button("Reset");
private final BorderPane mainLayout = new BorderPane();
public CenterView() {
listView = new ListView(centerViewModel.pagesProperty());
listView.getStylesheets().add(Objects.requireNonNull(getClass().getResource("/style/listview-config.css")).toExternalForm());
initialize();
}
private void initialize() {
listView.setCellFactory(param -> new PdfPageCell());
currentPage.addListener((obs, oldVal, newVal) -> loadPagesAround(newVal.intValue()));
listView.setOnDragOver(this::handleDragOver);
listView.setOnDragDropped(this::handleDragDropped);
resetButton.setOnAction(event -> {
pages.clear();
totalPagesLabel.setText("Total Pages: 0");
});
listView.setOnScroll(event -> {
int currentIndex = listView.getSelectionModel().getSelectedIndex();
if (event.getDeltaY() > 0 && currentIndex > 0) {
loadPagesAround(currentIndex - 5);
} else if (event.getDeltaY() < 0 && currentIndex < pages.size() - 1) {
loadPagesAround(currentIndex + 5);
}
});
listView.getSelectionModel().selectedIndexProperty().addListener((obs, oldSelection, newSelection) -> {
if (newSelection != null && newSelection.intValue() >= 0) {
loadPagesAround(newSelection.intValue());
}
});
mainLayout.setTop(resetButton);
mainLayout.setCenter(listView);
mainLayout.setBottom(totalPagesLabel);
totalPagesLabel.setStyle("-fx-padding: 10px;");
}
private class PdfPageCell extends ListCell {
private final StackPane stackPane = new StackPane();
private final ImageView imageView = new ImageView();
private final DropShadow dropShadow = new DropShadow(); // DropShadow instance
public PdfPageCell() {
dropShadow.setOffsetX(0);
dropShadow.setOffsetY(0);
dropShadow.setRadius(7);
dropShadow.setSpread(0.1);
dropShadow.setColor(Color.gray(0.1));
imageView.setEffect(dropShadow);
stackPane.getChildren().add(imageView);
imageView.setPreserveRatio(true);
imageView.setSmooth(true);
}
@Override
protected void updateItem(BufferedImage item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setGraphic(null);
} else {
// Convert the BufferedImage to JavaFX Image
imageView.setImage(SwingFXUtils.toFXImage(item, null));
// Set the ImageView to fill the entire cell size
imageView.fitWidthProperty().bind(stackPane.widthProperty());
imageView.fitHeightProperty().bind(stackPane.heightProperty());
setGraphic(stackPane);
}
}
}
public BorderPane getView() {
updateTotalPages();
return mainLayout;
}
private void loadPagesAround(int currentIndex) {
int totalPages = centerViewModel.getTotalPages();
int startIndex = Math.max(currentIndex - 5, 0);
int endIndex = Math.min(currentIndex + 5, totalPages - 1);
// Asynchronously preload pages
new Thread(() -> {
for (int i = startIndex; i
Подробнее здесь: [url]https://stackoverflow.com/questions/79372952/how-can-i-render-large-files-thousand-of-pages-using-the-conversion-of-pdf-file[/url]
Мобильная версия