如何在PyQt中使用pdf.js查看器渲染PDF?

6 投票
3 回答
16854 浏览
提问于 2025-04-18 04:52

我在我的项目中尝试添加pdf.js查看器的文件,结果在Chrome、Mozilla、Safari等浏览器中都能正常工作,但在node-webkit和PyQt的webkit中却无法加载某些页面。

我正在尝试通过一个iframe来加载这个文件,像这样:

<iframe src="/test/?file=/assets/pdf/example.pdf#page=3"> </iframe>

3 个回答

2

从PyQt5版本5.13开始,你可以使用Chromium的API来加载PDF文件。根据文档的说明,https://doc.qt.io/qt-5/qtwebengine-features.html#pdf-file-viewing,这个功能默认是开启的。

这个简单的例子是改编自简单浏览器

import sys
from pathlib import Path

from PyQt5 import QAxContainer
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLineEdit, QApplication


class Main(QWidget):
    def __init__(self, parent=None):
        super(Main, self).__init__(parent)
        self.main_layout = QVBoxLayout(self)

        self.qlineedit = QLineEdit()
        self.qlineedit.returnPressed.connect(self.go_action)
        self.main_layout.addWidget(self.qlineedit)
        self.read_btn = QPushButton('Test')
        self.read_btn.clicked.connect(self.go_action)
        self.main_layout.addWidget(self.read_btn)

        self.WebBrowser = QAxContainer.QAxWidget(self)
        self.WebBrowser.setFocusPolicy(Qt.StrongFocus)
        self.WebBrowser.setControl("{8856F961-340A-11D0-A96B-00C04FD705A2}")
        self.main_layout.addWidget(self.WebBrowser)

    def go_action(self):
        # convert system path to web path
        f = Path(self.qlineedit.text()).as_uri()
        # load object 
        self.WebBrowser.dynamicCall('Navigate(const QString&)', f)


if __name__ == "__main__":
    a = QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(a.exec_())

这个例子:

这个例子

9

下面是一些更新的示例脚本,用于在 pdf.js 中与 PyQt4/QtWebKit 或 PyQt5/QtWebEngine 一起使用。要尝试这些示例,首先需要 下载 pdf.js 的最新稳定版本,然后将压缩包解压到合适的位置。(注意:如果你使用的是 Linux,可能你的系统已经有 pdf.js 的软件包,可以直接安装那个。)

更新:

从 Qt-5.13.0 开始,也可以使用 内置的 Chromium PDF 查看器 和 QWebEngineView 一起使用:

截图

import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets

PDF = 'file://path/to/my/sample.pdf'

class Window(QtWebEngineWidgets.QWebEngineView):
    def __init__(self):
        super().__init__()
        self.settings().setAttribute(
            QtWebEngineWidgets.QWebEngineSettings.PluginsEnabled, True)
        self.settings().setAttribute(
            QtWebEngineWidgets.QWebEngineSettings.PdfViewerEnabled, True)
        self.load(QtCore.QUrl.fromUserInput(PDF))

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 50, 800, 600)
    window.show()
    sys.exit(app.exec_())

PyQt5/QtWebEngine 的 pdfjs 脚本:

更新:

注意:截至 2022 年 8 月,可能需要使用 pdfjs 的旧版构建(即在 下载页面上为“旧浏览器”提供的构建)来确保与 PyQt5 的兼容性。不过,稳定版应该可以正常与 PyQt6 一起使用。

截图

import sys
from PyQt5 import QtCore, QtWidgets, QtWebEngineWidgets

PDFJS = 'file:///path/to/pdfjs-1.9.426-dist/web/viewer.html'
# PDFJS = 'file:///usr/share/pdf.js/web/viewer.html'
PDF = 'file:///path/to/my/sample.pdf'

class Window(QtWebEngineWidgets.QWebEngineView):
    def __init__(self):
        super().__init__()
        self.load(QtCore.QUrl.fromUserInput('%s?file=%s' % (PDFJS, PDF)))

if __name__ == '__main__':

    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 50, 800, 600)
    window.show()
    sys.exit(app.exec_())

PyQt4/QtWebKit 的 pdfjs 脚本:

import sys
from PyQt4 import QtCore, QtGui, QtWebKit

PDFJS = 'file:///path/to/pdfjs-1.9.426-dist/web/viewer.html'
# PDFJS = 'file:///usr/share/pdf.js/web/viewer.html'
PDF = 'file:///path/to/my/sample.pdf'

class Window(QtWebKit.QWebView):
    def __init__(self):
        super().__init__()
        self.load(QtCore.QUrl.fromUserInput('%s?file=%s' % (PDFJS, PDF)))

if __name__ == '__main__':

    app = QtGui.QApplication(sys.argv)
    window = Window()
    window.setGeometry(600, 50, 800, 600)
    window.show()
    sys.exit(app.exec_())
7

我在Qt论坛上找到了一条帖子,里面有thebeast44发的Qt代码片段,回答了你的问题。下面是我把它转成Python的代码。

你还需要从作者的原始代码中解压出res文件夹,我觉得他只是修改了查看器... 我也把这段代码附在这里

from PyQt4 import QtCore
from PyQt4 import QtGui
from PyQt4 import QtNetwork
from PyQt4 import QtWebKit


class PDFViewer(QtWebKit.QWebView):
    pdf_viewer_page = 'res/pdf-viewer.html'

    def __init__(self, parent=None):
        super().__init__(parent)
        self.settings = QtWebKit.QWebSettings.globalSettings()
        self.settings.setAttribute(QtWebKit.QWebSettings.LocalContentCanAccessFileUrls, True )
        self.settings.setAttribute(QtWebKit.QWebSettings.LocalContentCanAccessRemoteUrls, True )
        self.settings.setAttribute(QtWebKit.QWebSettings.DeveloperExtrasEnabled, True )
        nam = QtNetwork.QNetworkAccessManager()
        page = QtWebKit.QWebPage(self)
        page.setNetworkAccessManager(nam)
        self.setPage(page)
        self.loadFinished.connect(self.onLoadFinish)
        self.setUrl(QtCore.QUrl(self.pdf_viewer_page))

    def onLoadFinish(self, success):
        if success:
            self.page().mainFrame().evaluateJavaScript("init();")


if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    viewer = PDFViewer(parent=None)
    viewer.show()
    sys.exit(app.exec_())

撰写回答