在JavaFX中显示pdf

JavaFX开发一个需要显示pdf的桌面应用程序。 我读到在JavaFX (当前版本)中不支持pdf查看/显示,我也读到了JPedal

现在,问题:

  1. 是否有任何外部组件或库可以在JavaFX中查看pdf? 它应该是一个免费软件。
  2. (如果我必须使用JPedal )如何将其嵌入我的应用程序中。

JPedalFX示例代码和用法

使用JPedalFX的示例代码随JPedalFX下载一起提供 。

在我这方面有点蹩脚,但我只是在这里粘贴从JPedalFX库提供的示例查看器中复制的片段示例代码。 代码依赖于JPedalFX发行版中包含的jpedal_lgpl.jar文件,该文件位于类路径(或应用程序jar清单中引用的库路径)上。

如果您对JPedalFX的使用有任何疑问,我建议您直接联系IDR解决方案 (他们过去一直对我做出回应)。

 // get file path. FileChooser fc = new FileChooser(); fc.setTitle("Open PDF file..."); fc.getExtensionFilters().add(new FileChooser.ExtensionFilter("PDF Files", "*.pdf")); File f = fc.showOpenDialog(stage.getOwner()); String filename = file.getAbsolutePath(); // open file. PdfDecoder pdf = new PdfDecoder(); pdf.openPdfFile(filename); showPage(1); pdf.closePdfFile(); . . . /** * Update the GUI to show a specified page. * @param page */ private void showPage(int page) { //Check in range if (page > pdf.getPageCount()) return; if (page < 1) return; //Store pageNumber = page; //Show/hide buttons as neccessary if (page == pdf.getPageCount()) next.setVisible(false); else next.setVisible(true); if (page == 1) back.setVisible(false); else back.setVisible(true); //Calculate scale int pW = pdf.getPdfPageData().getCropBoxWidth(page); int pH = pdf.getPdfPageData().getCropBoxHeight(page); Dimension s = Toolkit.getDefaultToolkit().getScreenSize(); s.width -= 100; s.height -= 100; double xScale = (double)s.width / pW; double yScale = (double)s.height / pH; double scale = xScale < yScale ? xScale : yScale; //Work out target size pW *= scale; pH *= scale; //Get image and set Image i = getPageAsImage(page,pW,pH); imageView.setImage(i); //Set size of components imageView.setFitWidth(pW); imageView.setFitHeight(pH); stage.setWidth(imageView.getFitWidth()+2); stage.setHeight(imageView.getFitHeight()+2); stage.centerOnScreen(); } /** * Wrapper for usual method since JFX has no BufferedImage support. * @param page * @param width * @param height * @return */ private Image getPageAsImage(int page, int width, int height) { BufferedImage img; try { img = pdf.getPageAsImage(page); //Use deprecated method since there's no real alternative //(for JavaFX 2.2+ can use SwingFXUtils instead). if (Image.impl_isExternalFormatSupported(BufferedImage.class)) return javafx.scene.image.Image.impl_fromExternalImage(img); } catch(Exception e) { e.printStackTrace(); } return null; } /** * =========================================== * Java Pdf Extraction Decoding Access Library * =========================================== * * Project Info: http://www.jpedal.org * (C) Copyright 1997-2008, IDRsolutions and Contributors. * * This file is part of JPedal * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * --------------- * JPedalFX.java * --------------- */ 

SwingLabs PDF渲染器

另外,我过去使用旧的基于SwingLabs Swing的pdf渲染器和JavaFX来渲染我的JavaFX Web浏览器的 pdf。 虽然Swing / JavaFX集成在我开发浏览器时并不是JavaFX的支持function,但它仍然适用于我。 集成代码在PDFViewer.java和BrowserWindow.java中 。

请注意,Java 2.2中支持在Swing应用程序中嵌入JavaFX ,Java 8中支持在JavaFX中嵌入Swing应用程序 。

我建议使用PDF JS javascript库。

创建一个WebView并静态加载此javascript pdf viewer示例项目的html / javascript内容。 在javascript中创建一个函数,您可以向其发送要显示的pdf字节数组。

这样,pdf查看器的所有逻辑都已存在。 您甚至可以修改查看器html以删除那里的某些function。

还要小心JPedalFX,因为我发现它必须渲染添加到pdf文件中的图像时不可靠。 在我的情况下,JPedalFX无法渲染使用jfreechart生成的图表图像

好的,这是我50美分。 除了@ALabrosik和@ReneEnriquez的答案。

下载pdf.js dist并将其放在src/main/resources

 ├── pom.xml ├── src │  └── main │  ├── java │  │  └── me │  │  └── example │  │  ├── JSLogListener.java │  │  ├── Launcher.java │  │  └── WebController.java │  └── resources │  ├── build │  │  ├── pdf.js │  │  └── pdf.worker.js │  ├── main.fxml │  ├── web │  │  ├── cmaps │  │  ├── compatibility.js │  │  ├── debugger.js │  │  ├── images │  │  ├── l10n.js │  │  ├── locale │  │  ├── viewer.css │  │  ├── viewer.html │  │  └── viewer.js 

创建以下fxml文件(您应该在TabPane或类似容器中包装WebView以避免滚动支持的问题)

        

要防止pdf.js在启动时打开demo pdf文件,请打开web/viewer.js并清除DEFAULT_URL值。

 var DEFAULT_URL = ''; 

打开web/viewer.html并添加脚本块:

        

现在是控制器(参见代码注释以获得解释)。

  public class WebController implements Initializable { @FXML private WebView web; @FXML private Button btn; public void initialize(URL location, ResourceBundle resources) { WebEngine engine = web.getEngine(); String url = getClass().getResource("/web/viewer.html").toExternalForm(); // connect CSS styles to customize pdf.js appearance engine.setUserStyleSheetLocation(getClass().getResource("/web.css").toExternalForm()); engine.setJavaScriptEnabled(true); engine.load(url); engine.getLoadWorker() .stateProperty() .addListener((observable, oldValue, newValue) -> { // to debug JS code by showing console.log() calls in IDE console JSObject window = (JSObject) engine.executeScript("window"); window.setMember("java", new JSLogListener()); engine.executeScript("console.log = function(message){ java.log(message); };"); // this pdf file will be opened on application startup if (newValue == Worker.State.SUCCEEDED) { try { // readFileToByteArray() comes from commons-io library byte[] data = FileUtils.readFileToByteArray(new File("/path/to/file")); String base64 = Base64.getEncoder().encodeToString(data); // call JS function from Java code engine.executeScript("openFileFromBase64('" + base64 + "')"); } catch (Exception e) { e.printStackTrace(); } } }); // this file will be opened on button click btn.setOnAction(actionEvent -> { try { byte[] data = FileUtils.readFileToByteArray(new File("/path/to/another/file")); String base64 = Base64.getEncoder().encodeToString(data); engine.executeScript("openFileFromBase64('" + base64 + "')"); } catch (Exception e) { e.printStackTrace(); } }); } } 

某些pdf.js函数不起作用:打开文件(因为pdf.js无法访问JAR之外的URL),打印等。要隐藏相应的工具栏按钮,可以将以下行添加到web.css:

 #toolbarViewerRight { display:none; } 

就这样。 其余的代码是微不足道的。

 public class JSLogListener { public void log(String text) { System.out.println(text); } } public class Launcher extends Application { public static void main(String[] args) { Application.launch(); } public void start(Stage primaryStage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("/main.fxml")); primaryStage.setTitle("PDF test app"); primaryStage.setScene(new Scene(root, 1280, 576)); primaryStage.show(); } } 

希望这对某人有帮助。

尝试JPedalFX在他们的网站上声明“JPedalFX是一个基于JavaFX 2的轻量级PDF查看器和JPedal的LGPL版本。它具有简单的界面,旨在快速方便地查看PDF文档。”

http://www.idrsolutions.com/jpedalfx-viewer/

还没有尝试但希望它有所帮助

您也可以尝试使用iText,我在java 中使用它有关如何使用它的教程

对于某些人来说,将PDF文档转换为HTML并使用WebView显示它可能是一种解决方法。

开源命令行工具pdf2htmlEx可生成非常漂亮的独立HTML文件,其中嵌入了图像和JavaScript。

ICEPDF非常易于使用,免费且轻量级。 我最近用它为我的公司制作一个小的PDF索引应用程序;)

我用Web视图和pdf.js编写了一个非常简单的例子,这里是GitHub上可用的源代码:

https://github.com/enriquezrene/curso-javafx-udemy/tree/master/clase-17/curso-javafx

好好享受!!!

 package de.vogella.itext.write; import java.io.FileOutputStream; import java.util.Date; import com.itextpdf.text.Anchor; import com.itextpdf.text.BadElementException; import com.itextpdf.text.BaseColor; import com.itextpdf.text.Chapter; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Element; import com.itextpdf.text.Font; import com.itextpdf.text.List; import com.itextpdf.text.ListItem; import com.itextpdf.text.Paragraph; import com.itextpdf.text.Phrase; import com.itextpdf.text.Section; import com.itextpdf.text.pdf.PdfPCell; import com.itextpdf.text.pdf.PdfPTable; import com.itextpdf.text.pdf.PdfWriter; public class FirstPdf { private static String FILE = "c:/temp/FirstPdf.pdf"; private static Font catFont = new Font(Font.FontFamily.TIMES_ROMAN, 18, Font.BOLD); private static Font redFont = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.NORMAL, BaseColor.RED); private static Font subFont = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.BOLD); private static Font smallBold = new Font(Font.FontFamily.TIMES_ROMAN, 12, Font.BOLD); public static void main(String[] args) { try { Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream(FILE)); document.open(); addMetaData(document); addTitlePage(document); addContent(document); document.close(); } catch (Exception e) { e.printStackTrace(); } } // iText allows to add metadata to the PDF which can be viewed in your Adobe // Reader // under File -> Properties private static void addMetaData(Document document) { document.addTitle("My first PDF"); document.addSubject("Using iText"); document.addKeywords("Java, PDF, iText"); document.addAuthor("Lars Vogel"); document.addCreator("Lars Vogel"); } private static void addTitlePage(Document document) throws DocumentException { Paragraph preface = new Paragraph(); // We add one empty line addEmptyLine(preface, 1); // Lets write a big header preface.add(new Paragraph("Title of the document", catFont)); addEmptyLine(preface, 1); // Will create: Report generated by: _name, _date preface.add(new Paragraph("Report generated by: " + System.getProperty("user.name") + ", " + new Date(), //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ smallBold)); addEmptyLine(preface, 3); preface.add(new Paragraph("This document describes something which is very important ", smallBold)); addEmptyLine(preface, 8); preface.add(new Paragraph("This document is a preliminary version and not subject to your license agreement or any other agreement with vogella.com ;-).", redFont)); document.add(preface); // Start a new page document.newPage(); } private static void addContent(Document document) throws DocumentException { Anchor anchor = new Anchor("First Chapter", catFont); anchor.setName("First Chapter"); // Second parameter is the number of the chapter Chapter catPart = new Chapter(new Paragraph(anchor), 1); Paragraph subPara = new Paragraph("Subcategory 1", subFont); Section subCatPart = catPart.addSection(subPara); subCatPart.add(new Paragraph("Hello")); subPara = new Paragraph("Subcategory 2", subFont); subCatPart = catPart.addSection(subPara); subCatPart.add(new Paragraph("Paragraph 1")); subCatPart.add(new Paragraph("Paragraph 2")); subCatPart.add(new Paragraph("Paragraph 3")); // add a list createList(subCatPart); Paragraph paragraph = new Paragraph(); addEmptyLine(paragraph, 5); subCatPart.add(paragraph); // add a table createTable(subCatPart); // now add all this to the document document.add(catPart); // Next section anchor = new Anchor("Second Chapter", catFont); anchor.setName("Second Chapter"); // Second parameter is the number of the chapter catPart = new Chapter(new Paragraph(anchor), 1); subPara = new Paragraph("Subcategory", subFont); subCatPart = catPart.addSection(subPara); subCatPart.add(new Paragraph("This is a very important message")); // now add all this to the document document.add(catPart); } private static void createTable(Section subCatPart) throws BadElementException { PdfPTable table = new PdfPTable(3); // t.setBorderColor(BaseColor.GRAY); // t.setPadding(4); // t.setSpacing(4); // t.setBorderWidth(1); PdfPCell c1 = new PdfPCell(new Phrase("Table Header 1")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); c1 = new PdfPCell(new Phrase("Table Header 2")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); c1 = new PdfPCell(new Phrase("Table Header 3")); c1.setHorizontalAlignment(Element.ALIGN_CENTER); table.addCell(c1); table.setHeaderRows(1); table.addCell("1.0"); table.addCell("1.1"); table.addCell("1.2"); table.addCell("2.1"); table.addCell("2.2"); table.addCell("2.3"); subCatPart.add(table); } private static void createList(Section subCatPart) { List list = new List(true, false, 10); list.add(new ListItem("First point")); list.add(new ListItem("Second point")); list.add(new ListItem("Third point")); subCatPart.add(list); } private static void addEmptyLine(Paragraph paragraph, int number) { for (int i = 0; i < number; i++) { paragraph.add(new Paragraph(" ")); } } }