PySide6でPDF.jsを使う

はじめに

以前PythonでPDFを扱う記事を書きました。
touch-sp.hatenablog.com
今回はPDF.jsを使って同じことをしてみました。

GUI周りはPyQt6からPySide6に変えています。PySide6にはWebEngineが組み込まれているので以下のようなインストールは不要になります。

pip install PyQt6-WebEngine

PDF.jsの導入

非常に簡単です。こちらからZIPファイルをダウンロードして解凍するだけです。


2022年10月1日現在最新の「pdfjs-2.16.105-dist.zip」をダウンロードしました。


解凍後のフォルダ構造はこのようになっています。

pdf_works
│
│  pdfviewer.py
│
└─pdfjs-2.16.105-dist
    │  LICENSE
    │
    ├─build
    │
    └─web
        │  compressed.tracemonkey-pldi-09.pdf
        │  debugger.css
        │  debugger.js
        │  viewer.css
        │  viewer.html
        │  viewer.js
        │  viewer.js.map
        │
        ├─cmaps
        │   
        ├─images
        │
        ├─locale
        │
        └─standard_fonts

Pythonスクリプト

上のフォルダ構造に含まれている「pdfviewer.py」です。

from PySide6.QtCore import QUrl
from PySide6.QtWidgets import QApplication, QMainWindow, QFileDialog
from PySide6.QtWebEngineWidgets import QWebEngineView 
from PySide6.QtGui import QAction
from functools import partial

PDFJS = 'file:///pdfjs-2.16.105-dist/web/viewer.html'
 
class Window(QMainWindow):
    def __init__(self):
        super().__init__()
        self.action = []
        self.pdf_file = ''
        self.initUI()
        
    def initUI(self):
        self.setWindowTitle("PDF Viewer")
        self.resize(1000,750)
 
        self.webView = QWebEngineView()

        self.setCentralWidget(self.webView)

        self.menubar = self.menuBar()

        self.file_menu = self.menubar.addMenu('ファイル')
        self.new_file =QAction('新規ファイル')
        self.file_menu.addAction(self.new_file)
        self.new_file.triggered.connect(self.showDialog1)        

        self.mokuji_menu = self.menubar.addMenu('目次')

        self.showDialog1()
        
    def showDialog1(self):
        fname = QFileDialog.getOpenFileName(self, 'Open PDF file', '', 'PDF files (*.pdf | *.PDF)')
        if fname[0]:

            self.pdf_file = fname[0]
            self.webView.load(QUrl(f'{PDFJS}?file={self.pdf_file}'))

            self.mokuji_menu.clear()
            self.mokuji_dict = {}
            self.action = []
            text_file = fname[0].replace('.PDF', '.txt').replace('.pdf', '.txt')
            with open(text_file, 'r', encoding='UTF-8') as f:
                for data in f:
                    data = data.rstrip()
                    if data != '':
                        each_line = data.split(',')
                        self.action.append(QAction(each_line[1].strip()))
                        self.mokuji_menu.addAction(self.action[-1])
                        self.action[-1].triggered.connect(partial(self.gotoPage, each_line[0].strip()))

    def gotoPage(self, x):
        self.webView.load(QUrl(f'{PDFJS}?file={self.pdf_file}#page={x}'))
        
if __name__ == '__main__':
    app = QApplication([])
    ex = Window()
    ex.show()
    app.exec()

使い方

こちらを参照して下さい。
touch-sp.hatenablog.com

補足

ただPDFファイルを開くだけのスクリプトはこのように簡単に書けます。

import os
from PySide6 import QtCore, QtWidgets, QtWebEngineWidgets

pdfjs = 'file:///pdfjs-2.16.105-dist/web/viewer.html'
pdf_path = os.path.join('..', '..', 'sample.pdf')

class Window(QtWebEngineWidgets.QWebEngineView):
    def __init__(self):
        super().__init__()
        self.resize(1000, 750)
        self.load(QtCore.QUrl(f'{pdfjs}?file={pdf_path}'))

if __name__ == '__main__':
    app = QtWidgets.QApplication([])
    ex = Window()
    ex.show()
    app.exec()



開くページ数や開き方を指定する場合にはこのようにします。

self.load(QtCore.QUrl(f'{pdfjs}?file={pdf_path}#page=4&zoom=page-width'))



zoomは以下のような設定が可能です。

自動ズーム:			zoom=auto (default)
ページのサイズに合わせる:	zoom=page-fit
幅に合わせる:			zoom=page-width
(倍率指定):			zoom=50 (50%の場合)