Python 在PyQt5中打印pdf文档

Python 在PyQt5中打印pdf文档,python,python-3.x,windows,printing,pyqt5,Python,Python 3.x,Windows,Printing,Pyqt5,我想用打印机打印pdf文档。到目前为止,我有这个代码 def printDialog(self): filePath, filter = QFileDialog.getOpenFileName(self, 'Open file', '', 'Text (*.txt);;PDF (*.pdf)') if not filePath: return file_extension = os.path.splitext(filePath)

我想用打印机打印
pdf
文档。到目前为止,我有这个代码

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

我不知道如何继续执行
TODO
部分。

一种可能是使用pdf2image,它是

一个python(3.5+)模块,包装pdftoppm和pdftocairo以将PDF转换为PIL图像对象

在上面的链接下,您将找到poppler的安装说明,它是模块的依赖项

步骤

  • PDF文件已读取
  • 借助pdf2image将其转换为图像
  • 每个图像都使用QPaint绘制
代码的简单版本如下所示:

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()
convert_from_path的第二个参数描述了dpi中的输出分辨率。设备坐标系中的目标矩形可以通过在QPaint实例上调用viewport来确定。最后,可以使用双线性滤波算法将图像平滑地缩放到目标矩形

独立样本程序

我稍微修改了您的代码,并创建了一个完全独立的示例

诸如纸张大小、分辨率、关于内存要求的优化和错误处理等主题不在讨论之列。其目的是给出一个最小的例子

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_())

你试过使用QWebEnginePage吗,我已经告诉过你两次了?@musicamante不,我现在不知道怎么做。@musicamante我可以用它打印某个目录中的所有文档(选择多个文档)吗?看看印刷的进展?e、 g.显示带有“printing doc1”、“printing doc2”等字样的消息框?在对上一个问题的回答中,我链接到了解释如何加载和打印html内容的其他答案。正如我告诉过你的,只需使用
setUrl()
。关于多重打印的答案是肯定的,但只有在您了解如何打印pdf文件后,才能在另一个问题中解决。@musicamante我开始尝试index.html,但遇到错误
self.\u page.print(self.\u printer,self.print\u completed)AttributeError:“窗口”对象没有属性“打印完成”
。我正在发送带有代码的pastebin,如果你能看一下的话,谢谢。它能转换成更大的图像吗?如何保持大小与输入pdf中的大小相同?我注意到我可以添加第二个参数来将_从_字节转换为dpi。但不知道保留pdf大小的正确值是什么。还有一个大小参数,但不知道正确的大小。dpi参数决定pdf到图像转换的质量。要填充整个页面,可以通过调用画师上的视口来确定设备坐标系中的目标矩形。然后,可以使用双线性滤波算法将图像平滑缩放到目标矩形。我已经相应地更新了答案和示例代码。页面底部写着:一个相对较大的PDF文件将耗尽您的所有内存并导致进程中止(除非您使用输出文件夹)。我已经更新了答案以使用输出文件夹变量。您还可以在此链接下找到更多性能提示。