I have a window with a QGraphicsScene as painter, and i want to render its elements to a pdf file on press of a button.
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()
nameItem on j is the name label for the line, m_items[4] is the name label for each circle.
My issue is that i cant seem to get the exact height of the rendered scene, moreover I have zero clue as to how i could overflow the text to the next page should the contents not fit in one.
it would be lovely if i could somehow render every line and its corresponding circles seperately for each connection, stored in lineList
note: the line is a child of every circle , and the names of every line and circle are children of theirs, implemented much in the same way as the answer to my previous question where in lies my final issue of the grip items also being rendered.
I have discovered that I can create a new scene, move each item one by one and render it out to the pdf but this raises two separate issues
- I cant add a line break and avoid overdrawing the new render over the previous one, and
- I cant position the text as addText doesnt take positional arguments.
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_())
if possible , the ability to print, test then circle for all circles would be decent enough for me.
Incorrect output example: