将项目打印为pdf

问题描述 投票:0回答:1

我有一个带有QGraphicsScene作为画家的窗口,我想通过按一下按钮将其元素渲染为pdf文件。

def generateReport(self):
        lineList = {}
        for i in self.circleList:
            for j,k in i.lineItems:
                if j not in lineList:
                    lineList[j] = [i, k]
        printed = QPdfWriter("Output.pdf")
        printed.setPageSize(QPagedPaintDevice.A4)
        printer = QPainter(printed)
        self.painter.render(printer)
        for i,j in enumerate(lineList):
            # j.scene().render(printer)
            # lineList[j][0].scene().render(printer)
            # lineList[j][1].scene().render(printer)
            printer.drawText(0, self.painter.height() + i*200, f'{j.nameItem.toPlainText()}: {lineList[j][0].m_items[4].toPlainText()}, {lineList[j][1].m_items[4].toPlainText()}')
        printer.end()

j上的nameItem是该行的名称标签,m_items [4]是每个圆的名称标签。

[我的问题是,我似乎无法获得渲染场景的确切高度,而且,如果内容不合一,我将如何使文本溢出到下一页的线索为零。

如果我能以某种方式为每个连接分别渲染每一行及其对应的圆并存储在lineList中,那将是很可爱的

注意:这条线是每个圆的子代,每个线和圆的名称是它们的子代,其实现方式与我对previous question的答案的处理方式大致相同,这是我最后一次抓握项目所在也正在渲染。

我发现我可以创建一个新场景,将每个项目一个接一个地移动并渲染到pdf中,但这会引起两个单独的问题

  1. 我不能添加换行符,并避免在前一个渲染图上过度绘制新渲染图,并且
  2. 我无法放置文本,因为addText不接受位置参数。

MRE:

import random
from fbs_runtime.application_context.PyQt5 import ApplicationContext
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPainter, QPdfWriter, QBrush, QPagedPaintDevice
from PyQt5.QtWidgets import (QDialog, QGraphicsScene,
                             QGraphicsView, QGridLayout,
                             QPushButton, QGraphicsEllipseItem)

class gui(QDialog):
    def __init__(self, parent=None):
        super(gui, self).__init__(parent)
        self.resize(1280, 720)
        self.painter = QGraphicsScene(0, 0, self.width() - 50, self.height() - 70)
        self.painter.setBackgroundBrush(QBrush(Qt.white))
        self.canvas = QGraphicsView(self.painter)
        mainLayout = QGridLayout()
        mainLayout.addWidget(self.canvas, 0, 0, -1, -1)
        self.setLayout(mainLayout)

    @property
    def circleList(self):
        return [item for item in self.painter.items() if isinstance(item, QGraphicsEllipseItem)]

    def newCircle(self):
        self.painter.addEllipse( random.randint(100, 400), random.randint(100, 400), 50 + random.random() * 200, 50 + random.random() * 200)

    def generateReport(self):
        printed = QPdfWriter("Output.pdf")
        printed.setPageSize(QPagedPaintDevice.A4)
        printer = QPainter(printed)
        self.painter.render(printer)
        for i,j in enumerate(self.circleList):
            printer.drawText(0, printer.viewport().height() + i*200, 'test')
        printer.end()


if __name__ == "__main__":
    app = ApplicationContext()
    test = gui()
    test.newCircle()
    test.newCircle()
    test.newCircle()
    test.generateReport()
    test.show()
    exit(app.app.exec_())

[如果可能的话,可以打印,测试然后对所有圆圈进行圈出对我来说是足够体面的。

不正确的输出示例:

enter image description here

python pyqt pyqt5
1个回答
0
投票

要了解绘画是什么样的,您必须了解QGraphicsScene::render()方法的工作原理:

void QGraphicsScene :: render(QPainter * painter,const QRectF&target = QRectF(),const QRectF&source = QRectF(),Qt :: AspectRatioMode AspectRatioMode = Qt :: KeepAspectRatio)

使用画家将源矩形从场景渲染到目标。这个功能对于将场景的内容捕获到绘画设备,例如QImage(例如进行屏幕截图),或用于用QPrinter打印。例如:

QGraphicsScene::render()

如果source是一个null rect,则此函数将使用sceneRect()来确定要渲染的内容。如果target为null rect,则尺寸为将使用画家的油漆设备。

源rect内容将根据AspectRatioMode以适合目标矩形。默认情况下,方面比率保持不变,并且缩放源以适合目标。

另请参见QGraphicsView :: render()。

在您的情况下,如果未通过源,则将复制整个sceneRect(0、0、1230、650),并将其绘制在pdf页面上,如果大小不匹配,则会缩放大小。因此,从上面可以得出结论,如果要打印项目,则必须将其在场景中占据的空间作为源传递,并隐藏其他项目,而目标是要绘制的位置,这涉及到计算新的位置取决于上一个项目的打印位置。

考虑到上述,可能的解决方案如下:

QGraphicsScene scene;
scene.addItem(...
...
QPrinter printer(QPrinter::HighResolution);
printer.setPaperSize(QPrinter::A4);

QPainter painter(&printer);
scene.render(&painter);
© www.soinside.com 2019 - 2024. All rights reserved.