简体   繁体   English

在 PyQt5 中打印 pdf 文档

[英]Print pdf document in PyQt5

I'd like to print pdf document to a printer.我想将pdf文档打印到打印机。 So far, I have this code.到目前为止,我有这个代码。

def printDialog(self):
        filePath, filter = QFileDialog.getOpenFileName(self, 'Open file', '', 'Text (*.txt);;PDF (*.pdf)')
        if not filePath:
          return
        file_extension = os.path.splitext(filePath)[1]
        if file_extension == ".txt":
            doc = QtGui.QTextDocument()
            try:
                with open(filePath, 'r') as txtFile:
                    doc.setPlainText(txtFile.read())
                printer = QPrinter(QPrinter.HighResolution)
                if not QPrintDialog(printer, self).exec_():
                    return
                doc.print_(printer)
            except Exception as e:
                print('Error trying to print: {}'.format(e))
        elif file_extension == ".pdf":
            printer = QPrintDialog(QPrinter.HighResolution)
            printer.setOutputFormat(QPrinter.PdfFormat)
            printer.setOutputFileName(filePath)
            # TODO
        else:
            pass

I don't know how to continue in the TODO section.我不知道如何在TODO部分继续。

One possibility would be to use pdf2image which is一种可能性是使用 pdf2image 这是

A python (3.5+) module that wraps pdftoppm and pdftocairo to convert PDF to a PIL Image object一个 python (3.5+) 模块,它包装了 pdftoppm 和 pdftocairo 以将 PDF 转换为 PIL Image 对象

see https://pypi.org/project/pdf2image/https://pypi.org/project/pdf2image/

Under the link above you will find installation instructions for poppler, which is a dependency of the module.在上面的链接下,您将找到 poppler 的安装说明,它是该模块的依赖项。

Steps脚步

  • PDF file is readed阅读PDF文件
  • it is converted into images with help of pdf2image它在 pdf2image 的帮助下转换为图像
  • each image is painted using QPaint每个图像都是使用 QPaint 绘制的

A simple version of the code would look like this:代码的简单版本如下所示:

images = convert_from_path(filePath, dpi=300, output_folder=path)
painter = QPainter()
painter.begin(printer)
for i, image in enumerate(images):
    if i > 0:
        printer.newPage()
    rect = painter.viewport()
    qtImage = ImageQt(image)
    qtImageScaled = qtImage.scaled(rect.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
    painter.drawImage(rect, qtImageScaled)
painter.end()

The second parameter of convert_from_path describes the output resolution in dpi. convert_from_path 的第二个参数描述了以 dpi 为单位的输出分辨率。 The target rectangle in the device coordinate system can be determined by calling viewport on the QPainter instance.设备坐标系中的目标矩形可以通过在 QPainter 实例上调用 viewport 来确定。 Finally, the image can then be smoothly scaled to the target rectangle using a bilinear filter algorithm.最后,可以使用双线性滤波器算法将图像平滑地缩放到目标矩形。

Self-contained Sample Program自包含的示例程序

I have slightly modified your code and created a completely self-contained example.我稍微修改了您的代码并创建了一个完全独立的示例。

Topics such as paper sizes, resolutions, optimization regarding memory requirements and error handling etc. are not handled.不处理诸如纸张大小、分辨率、有关内存要求的优化和错误处理等主题。 The intention is rather to give a minimal example.目的是给出一个最小的例子。

import os
import sys

from PIL.ImageQt import ImageQt
from PyQt5 import QtWidgets
from PyQt5.QtCore import QSize, Qt
from PyQt5.QtGui import QPainter
from PyQt5.QtPrintSupport import QPrintDialog, QPrinter
from PyQt5.QtWidgets import QMainWindow, QFileDialog, QPushButton
import tempfile

from pdf2image import convert_from_path


class PrintDemo(QMainWindow):

    def __init__(self):
        QMainWindow.__init__(self)

        self.setMinimumSize(QSize(192, 128))
        self.setWindowTitle("Print Demo")

        printButton = QPushButton('Print', self)
        printButton.clicked.connect(self.onPrint)
        printButton.resize(128, 32)
        printButton.move(32, 48)

    def onPrint(self):
        self.printDialog()

    def printDialog(self):
        filePath, filter = QFileDialog.getOpenFileName(self, 'Open file', '', 'PDF (*.pdf)')
        if not filePath:
            return
        file_extension = os.path.splitext(filePath)[1]

        if file_extension == ".pdf":
            printer = QPrinter(QPrinter.HighResolution)
            dialog = QPrintDialog(printer, self)
            if dialog.exec_() == QPrintDialog.Accepted:
                with tempfile.TemporaryDirectory() as path:
                    images = convert_from_path(filePath, dpi=300, output_folder=path)
                    painter = QPainter()
                    painter.begin(printer)
                    for i, image in enumerate(images):
                        if i > 0:
                            printer.newPage()
                        rect = painter.viewport()
                        qtImage = ImageQt(image)
                        qtImageScaled = qtImage.scaled(rect.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation)
                        painter.drawImage(rect, qtImageScaled)
                    painter.end()
        else:
            pass


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    mainWin = PrintDemo()
    mainWin.show()
    sys.exit(app.exec_())

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM