首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在JavaFX中显示pdf

在JavaFX中显示pdf
EN

Stack Overflow用户
提问于 2013-08-13 10:49:27
回答 4查看 49.3K关注 0票数 21

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

现在,问题:

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

回答 4

Stack Overflow用户

回答已采纳

发布于 2013-08-13 21:19:19

JPedalFX示例代码和用法

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

就我而言,这有点蹩脚,但我将粘贴从JPedalFX库提供的示例查看器中复制的示例代码片段。代码依赖于包含在类路径上的jpedal_lgpl.jar文件(或应用程序jar清单中引用的库路径)。

如果您对JPedalFX的使用有进一步的疑问,我建议您使用直接联系IDR解决方案 (它们过去对我有响应)。

代码语言:javascript
复制
// 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网页浏览器渲染pdf。虽然在我开发浏览器时,Swing/JavaFX集成并不是JavaFX的一个受支持的特性,但它对我来说仍然很好。集成代码在PDFViewer.javaBrowserWindow.java中。

注意,Java2.2支持在Swing应用程序中嵌入JavaFX,Java8支持在JavaFX中嵌入Swing应用程序

票数 13
EN

Stack Overflow用户

发布于 2017-02-04 12:26:46

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

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

代码语言:javascript
复制
├── 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文件(您应该将WebView包装在TabPane或类似的容器中,以避免滚动支持方面的问题)

代码语言:javascript
复制
<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Tab?>
<?import javafx.scene.control.TabPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.web.WebView?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="576.0" prefWidth="1024.0" xmlns="http://javafx.com/javafx/8.0.112" xmlns:fx="http://javafx.com/fxml/1" fx:controller="me.example.WebController">
    <center>
      <TabPane>
         <tabs>
            <Tab text="PDF test">
               <content>
                    <WebView fx:id="web" minHeight="-1.0" minWidth="-1.0" />
               </content>
            </Tab>
         </tabs>
      </TabPane>
    </center>
   <bottom>
      <Button fx:id="btn" mnemonicParsing="false" text="Open another file" BorderPane.alignment="CENTER" />
   </bottom>
</BorderPane>

为了防止pdf.js在启动时打开演示pdf文件,打开web/viewer.js并清除DEFAULT_URL值。

代码语言:javascript
复制
var DEFAULT_URL = '';

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

代码语言:javascript
复制
<head>

<!-- ... -->
<script src="viewer.js"></script>

<!-- CUSTOM BLOCK -->
<script>
    var openFileFromBase64 = function(data) {
        var arr = base64ToArrayBuffer(data);
        console.log(arr);
        PDFViewerApplication.open(arr);
    }

    function base64ToArrayBuffer(base64) {
      var binary_string = window.atob(base64);
      var len = binary_string.length;
      var bytes = new Uint8Array( len );
      for (var i = 0; i < len; i++)        {
          bytes[i] = binary_string.charCodeAt(i);
      }
      return bytes.buffer;
    }
</script>
<!-- end of CUSTOM BLOCK -->

</head>

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

代码语言:javascript
复制
 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外部的pdf.js)、打印等。要隐藏相应的工具栏按钮,可以向web.css添加以下行:

代码语言:javascript
复制
#toolbarViewerRight {
    display:none;
}

就这样。其余的代码都是琐碎的。

代码语言:javascript
复制
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();
    }
}

希望这对某人有帮助。

票数 12
EN

Stack Overflow用户

发布于 2015-10-28 15:25:06

我建议使用PDF JS javascript库。

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

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

另外,要小心JPedalFX,因为我发现它在必须呈现被添加到pdf文件中的图像时不可靠。在我的例子中,JPedalFX无法呈现由jfreechart生成的图表图像。

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18207116

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档