JavaFX应用中显示PDF的可行方案咨询(多种尝试遇阻)
Hey Steve, I totally get how frustrating it can be to hunt for a PDF display solution that checks all your boxes—no Swing hacks, no messy resource folder workarounds, no pricey libraries. Let’s walk through some practical, Maven-friendly options that fit your needs:
1. Apache PDFBox + JavaFX Canvas
Apache PDFBox is a rock-solid open-source PDF processing library that integrates smoothly with Maven, and we can use it to render PDF pages directly to a JavaFX Canvas (no Swing components cluttering your UI).
Step 1: Add Maven Dependency
Drop this into your pom.xml to pull in PDFBox:
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.32</version> <!-- Use the latest stable version available --> </dependency>
Step 2: Basic Rendering Code
Here’s a quick example to load a PDF and render its first page to a JavaFX Canvas:
import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.rendering.PDFRenderer; import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.image.WritableImage; import javafx.scene.layout.StackPane; import javafx.stage.Stage; import javafx.embed.swing.SwingFXUtils; import java.io.File; public class PDFCanvasViewer extends Application { @Override public void start(Stage stage) throws Exception { File targetPDF = new File("your-document-path.pdf"); try (PDDocument document = PDDocument.load(targetPDF)) { PDFRenderer renderer = new PDFRenderer(document); // Render first page to a BufferedImage java.awt.image.BufferedImage awtImage = renderer.renderImage(0); // Convert to JavaFX-compatible image WritableImage fxImage = SwingFXUtils.toFXImage(awtImage, null); // Draw image to Canvas Canvas canvas = new Canvas(fxImage.getWidth(), fxImage.getHeight()); GraphicsContext gc = canvas.getGraphicsContext2D(); gc.drawImage(fxImage, 0, 0); StackPane root = new StackPane(canvas); Scene scene = new Scene(root, fxImage.getWidth(), fxImage.getHeight()); stage.setScene(scene); stage.show(); } } public static void main(String[] args) { launch(args); } }
Note: We only use SwingFXUtils for image conversion—no Swing UI components appear in your final JavaFX app.
2. WebView + PDF.js via WebJars (Maven-Managed)
You mentioned PDF.js felt off-limits because you didn’t want to manually add it to your resources folder—but WebJars solves that! WebJars packages front-end libraries into Maven artifacts, so you can pull PDF.js directly through your build file and access it from the classpath.
Step 1: Add WebJars Dependency
Add these lines to your pom.xml:
<dependency> <groupId>org.webjars</groupId> <artifactId>pdfjs</artifactId> <version>3.11.174</version> <!-- Grab the latest stable version --> </dependency>
Step 2: Load PDF.js in WebView
Instead of a local HTML file, we’ll build the viewer HTML dynamically and point to the WebJars-hosted PDF.js files:
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; public class PDFJSWebViewViewer extends Application { @Override public void start(Stage stage) { WebView webView = new WebView(); WebEngine webEngine = webView.getEngine(); // Get paths to PDF.js files from WebJars classpath String pdfJsCore = getClass().getResource("/META-INF/resources/webjars/pdfjs/3.11.174/build/pdf.js").toExternalForm(); String pdfJsWorker = getClass().getResource("/META-INF/resources/webjars/pdfjs/3.11.174/build/pdf.worker.js").toExternalForm(); // Dynamic HTML to render the PDF String viewerHtml = String.format(""" <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <style>body { margin: 0; } #viewer { width: 100vw; height: 100vh; }</style> </head> <body> <div id="viewer"></div> <script> pdfjsLib.GlobalWorkerOptions.workerSrc = '%s'; async function loadPDF() { const pdfDoc = await pdfjsLib.getDocument('your-document-path.pdf').promise; const firstPage = await pdfDoc.getPage(1); const viewport = firstPage.getViewport({ scale: 1.2 }); const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); canvas.width = viewport.width; canvas.height = viewport.height; document.getElementById('viewer').appendChild(canvas); await firstPage.render({ canvasContext: ctx, viewport: viewport }).promise; } loadPDF(); </script> <script src="%s"></script> </body> </html> """, pdfJsWorker, pdfJsCore); webEngine.loadContent(viewerHtml); Scene scene = new Scene(webView, 800, 600); stage.setScene(scene); stage.show(); } public static void main(String[] args) { launch(args); } }
All PDF.js files are managed by Maven—no manual resource folder setup required.
3. iText 7 + JavaFX (AGPL License)
If you’re comfortable with the AGPL license (make sure to adhere to its terms for distributed apps), iText 7 offers powerful PDF parsing tools. You can use it to convert PDF pages to images and display them in JavaFX ImageView or Canvas, similar to the PDFBox approach.
Maven Dependency
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>7.2.5</version> <!-- Latest stable version --> </dependency>
内容的提问来源于stack exchange,提问作者Steve2Fish

