【问题标题】:PDF output not working with Pyqt5 and Python 3.5PDF 输出不适用于 Pyqt5 和 Python 3.5
【发布时间】:2018-02-18 10:18:03
【问题描述】:

我已经为此测试了至少 20 种不同的解决方法。

我想打印一个小部件。

我的小部件是一个发票,它包含在许多其他小部件中,例如 QLineEdits、带有文本的 QLabels、充当图像的 QLabels、QDropDown 菜单等。这是一个屏幕截图(像 NIF 这样的所有数据都是临时占位符真正的企业):

所以应该很容易吧?好像不是这样的。

  1. 首先我尝试将它发送到打印机,仅此一项就很难处理许多不同的打印特定选项。经过我所有的研究,我发现 QPrintDialog 可以处理大部分内容
  2. 在测试了一段时间后,我注意到它可以很好地抓取小部件,但它会将它打印到一个非常小的部分,所以经过大量研究后,我找到了一种扩展它的方法,这就是我最终的结果。李>

代码:

def print_as_pdf(widgettoprint):
    # Printer
    printer = QPrinter()
    setupdialog = QPrintDialog(printer, widgettoprint)
    if setupdialog.exec() == QPrintDialog.Accepted:
        # Renderer
        painter = QPainter(printer)
        painter.begin(printer)
        # Scale it
        xscale = printer.pageRect().width() / widgettoprint.width()
        yscale = printer.pageRect().height() / widgettoprint.height()
        scale = min(xscale, yscale)
        painter.translate(printer.paperRect().x() + printer.pageRect().width() / 2,
                          printer.paperRect().y() + printer.pageRect().height() / 2)
        painter.scale(scale, scale)
        painter.translate(-1 * widgettoprint.width() / 2, -1 * widgettoprint.height() / 2)
        widgettoprint.render(painter)
        painter.end()
        return True
    else:
        return False

它成功了,它按预期打印了整个 A4 页面,但是文本的质量很差。我发现它只是截取它而不是将数据保存为文本或矢量数据。

所以这对我不起作用,但我必须尝试。我尝试使用相同的方法(选择 PDF 作为打印机)打印为 PDF,它只是生成一个带有屏幕截图的 PDF。我无法选择或复制文本数据。

  1. 所以我研究了替代品。我找到了Reportlab,但无法让它工作。我也尝试过PyFPDF,但特别是在不选择打印机的情况下创建 PDF 会破坏将发票实际打印到其他打印机的能力。
  2. 好吧,我花了几天的挫折试图寻找替代方案,而不是从头开始重建我的 7000 行代码程序。我找到了this blog about jinja2 and qt 解决方法,并决定试一试。将整个发票重新创建为 HTML 模板将是一项相当大的工作(因为有更多不同的发票,而不仅仅是这张)。但是出现了一个新问题,PyQt5 没有 QtWebKit 或 QWebView,据我所知,使用此代码和 QtWebEngine 打印一个白色的空 PDF:

代码:

import os
from jinja2 import Environment, FileSystemLoader
from PyQt5 import QtWebEngineWidgets
from PyQt5.QtPrintSupport import QPrinter, QPrintDialog
from PyQt5.QtGui import QPainter

PATH = os.path.dirname(os.path.abspath(__file__))
TEMPLATE_ENVIRONMENT = Environment(
    autoescape=False,
    loader=FileSystemLoader(os.path.join(PATH, 'userfiles/templates')),
    trim_blocks=False)

def render_template(template_filename, context):
    return TEMPLATE_ENVIRONMENT.get_template(template_filename).render(context)

def test():
    something = ['something1', 'something2', 'something3']
    context = {
        'something': something,
        'invoicenumber': "17012"
    }
    # Generate the HTML data with the template without creating a file, on-the-fly
    html = render_template('invoices.html', context)

    # add html to a webengine/widget
    web = QtWebEngineWidgets.QWebEngineView()
    web.page().setHtml(html)

    # Print that widget
    printer = QPrinter()
    setupdialog = QPrintDialog(printer)
    if setupdialog.exec() == QPrintDialog.Accepted:
        web.render(printer)
        print("done")

test()

HTML 模板在哪里:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Factura {{ invoicenumber }}</title>
</head>
<body>
<center>
    <h1>Factura {{ invoicenumber }}</h1>
    <p>{{ something|length }} something</p>
</center>
<ol align="left">
{{ something[0] }}
{{ something[1] }}
{{ something[2] }}
</ol>
</body>
</html>

我可能会花费更多的几周和几个月的时间来尝试实现这一目标。打印本来应该很容易,因为市场上的每个随机程序似乎都能够打印或创建 PDF,但现在对我来说,这是我编程学习经历中最糟糕的部分。

目标: 这个问题旨在为我的问题找到永久解决方案:如何将我的发票小部件打印到可选(Windows 平台)打印机?然后,如果选择了 PDF 打印机,请使用矢量或其他任何不创建屏幕截图的方式以无限质量进行打印。

由于我仍在学习(编程、Python 和 Qt),我也希望能解释我做错了什么。

【问题讨论】:

  • 您需要show() 网络视图才能获得一些可见的输出。然而,当我在 linux 上尝试这个时,结果并不是那么令人印象深刻。如果您使用的是 Windows,您可能想尝试像这样创建打印机:QPrinter(QPrinter.HighResolution)
  • PS:AFAICS,通过网络视图渲染只会创建一个包含图像的 pdf。因此,如果我正确理解了您的要求,它似乎并没有真正让您有所收获。
  • 嗯,那它确实也行不通。我该怎么办?
  • 你读过 Qt Wiki 上的Handling PDF 吗?这有很多有用的建议。
  • 实际上,我认为您可以使用QTextDocument 实现您想要的 - 我什至已经提供了如何在 SO 上做到这一点的示例!请参阅this answerthis answer。我刚刚测试了第一个,并且可以确认可以选择和复制生成的 pdf 的单个文本元素。

标签: python printing pyqt


【解决方案1】:

虽然我自己在 python 中编程,但我对在其中编程 GUI 知之甚少。但是,我发现了几个问题和站点,可以作为您自己实施的起点。我知道其中一些是 QT4,但请看一看,我相信事情并没有太大变化(但我可能是错的):
Pyqt take screenshot of certain screen area
Screenshot of a window using python
@ 987654323@
https://github.com/Python-Devs-Brasil/PyQt5-Tutorials/blob/master/Post-2(QtCore)/screenshot.py
https://github.com/baoboa/pyqt5/blob/master/examples/desktop/screenshot.py
How to grab a desktop screenshot with PyQt?

编辑
您是否尝试过通过 matplotlib 保存到 pdf 文件?
https://pythonspot.com/en/matplotlib-save-figure-to-image-file/
saving images in python at a very high quality

编辑 2
另外,看看这个
Create a pdf with fillable fields python

编辑 3
您还可以查看此问题中提到的库的文档和示例
Python PDF library

【讨论】:

  • 感谢您的回答,但我认为您错过了目标 :(。所有这些链接旨在捕获屏幕截图,我已经能够做到。我的目标不是那个。我的目标是将 PDF 打印为“不是”屏幕截图,因为否则您无法使用鼠标选择 PDF 上的数据。所需的解决方案需要将 PDF 呈现为布局(将转换视为 PDF 到 HTML 的示例。如果结果只是一个屏幕截图,那么它是 HTML 的意义是没有用的。PNG 可以工作。但你需要它 HTML 来选择数据/捕获/编辑数据)。我需要我的发票为 PDF,但不是屏幕截图。
  • 第二次编辑可能是我需要的。我正在检查它。
  • 请告诉我第二次编辑中的问题是否有帮助。
猜你喜欢
  • 2016-10-25
  • 1970-01-01
  • 1970-01-01
  • 2016-10-08
  • 2019-08-16
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 2017-03-24
相关资源
最近更新 更多