如何正确设置打印机的painter?
How to set painter of printer correctly?
我正在打印一组 table,每个 table 应该有自己的页面并且可能很长。基础工作正常,但我没有绘制页脚。问题是页脚将在额外的文档中绘制。
根据文档,我必须为设备设置画家。设备是 painter,这是正确的,但是我如何将 painter 设置到正确的 Block?还是这样做不对?
目标是使用此文档两次。第一次尝试是打印,第二次是 QTextDocument
,我可以在其中获取 QTextTable
并使用另一个文档元素对其进行编译。
工作示例
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtPrintSupport import *
content = [['section 1', [1,2,3,4]],['section2', [5,6,7,8]]]
app = QApplication(sys.argv)
document = QTextDocument ()
printer = QPrinter()
painter = QPainter(printer)
pageRect = printer.pageRect ()
tableFormat = QTextTableFormat ()
cellBlockFormat = QTextBlockFormat ()
cellCharFormat = QTextCharFormat ()
cellCharFormat.setFont (QFont ("Arial", 10))
for rownr, line in enumerate(content):
cursor = QTextCursor (document)
mainFrame = cursor.currentFrame ()
# header
cursor.setPosition (mainFrame.firstPosition ())
cursor.insertHtml ("This is the table for %s"%line[0])
# table
table = cursor.insertTable (3, 4, tableFormat)
for colnr, col in enumerate(line[1]):
print("col:", col)
cellCursor = table.cellAt (rownr + 1, colnr).firstCursorPosition ()
cellCursor.setBlockFormat (cellBlockFormat)
cellCursor.insertText (str (col))
#footer
painter.begin(printer)
painter.drawText (0, pageRect.bottom(), "I may be the footer")
painter.end()
# section finished
cursor.setPosition (mainFrame.lastPosition ())
tableFormat.setPageBreakPolicy (QTextFormat.PageBreak_AlwaysAfter)
cursor.insertBlock (cellBlockFormat, cellCharFormat)
document.print_(printer)
前提:这与其说是一种解决方案,不如说是一种黑客攻击,因为它是一种肮脏的解决方法。
想法是子类化 QPrinter,覆盖 newPage
方法并相应地绘制页脚。这需要使用页脚手动更新 printer
实例。
不幸的是,还有一个重要问题:只要只有一页,我就无法打印页脚。
过几天我再研究一下,看看有没有解决办法。
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtPrintSupport import *
class FooterPrinter(QPrinter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.footers = {}
def paintEngine(self, *args):
engine = super().paintEngine(*args)
self.currentPage = 0
return engine
def drawFooter(self):
text = self.footers.get(self.currentPage)
if not text:
return
painter = super().paintEngine().painter()
dpiy = painter.device().logicalDpiY()
margin = dpiy * (2/2.54)
rect = QRectF(margin, margin, self.width() - margin * 2, self.height() - margin * 2)
fm = QFontMetrics(painter.font(), painter.device())
size = fm.size(0, text)
painter.drawText(rect.left(), rect.bottom() - size.height(),
size.width(), size.height(), Qt.AlignLeft|Qt.AlignTop, text)
def newPage(self):
self.drawFooter()
newPage = super().newPage()
if newPage:
self.currentPage += 1
self.drawFooter()
return newPage
content = [['section 1', [1,2,3,4]],['section2', [5,6,7,8]]]
app = QApplication(sys.argv)
document = QTextDocument()
printer = FooterPrinter()
printer.setOutputFileName('/tmp/test.pdf')
pageRect = printer.pageRect ()
tableFormat = QTextTableFormat ()
cellBlockFormat = QTextBlockFormat ()
cellCharFormat = QTextCharFormat ()
cellCharFormat.setFont (QFont ("Arial", 10))
for rownr, line in enumerate(content):
cursor = QTextCursor (document)
mainFrame = cursor.currentFrame ()
# header
cursor.setPosition (mainFrame.firstPosition ())
cursor.insertHtml ("This is the table for %s"%line[0])
# table
table = cursor.insertTable (3, 4, tableFormat)
for colnr, col in enumerate(line[1]):
cellCursor = table.cellAt (rownr + 1, colnr).firstCursorPosition ()
cellCursor.setBlockFormat (cellBlockFormat)
cellCursor.insertText (str (col))
cursor.setPosition (mainFrame.lastPosition ())
tableFormat.setPageBreakPolicy (QTextFormat.PageBreak_AlwaysAfter)
cursor.insertBlock (cellBlockFormat, cellCharFormat)
printer.footers[rownr] = 'Note for page {}: some text.\nNew line\nAnother new line'.format(rownr + 1)
document.print_(printer)
我正在打印一组 table,每个 table 应该有自己的页面并且可能很长。基础工作正常,但我没有绘制页脚。问题是页脚将在额外的文档中绘制。
根据文档,我必须为设备设置画家。设备是 painter,这是正确的,但是我如何将 painter 设置到正确的 Block?还是这样做不对?
目标是使用此文档两次。第一次尝试是打印,第二次是 QTextDocument
,我可以在其中获取 QTextTable
并使用另一个文档元素对其进行编译。
工作示例
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtPrintSupport import *
content = [['section 1', [1,2,3,4]],['section2', [5,6,7,8]]]
app = QApplication(sys.argv)
document = QTextDocument ()
printer = QPrinter()
painter = QPainter(printer)
pageRect = printer.pageRect ()
tableFormat = QTextTableFormat ()
cellBlockFormat = QTextBlockFormat ()
cellCharFormat = QTextCharFormat ()
cellCharFormat.setFont (QFont ("Arial", 10))
for rownr, line in enumerate(content):
cursor = QTextCursor (document)
mainFrame = cursor.currentFrame ()
# header
cursor.setPosition (mainFrame.firstPosition ())
cursor.insertHtml ("This is the table for %s"%line[0])
# table
table = cursor.insertTable (3, 4, tableFormat)
for colnr, col in enumerate(line[1]):
print("col:", col)
cellCursor = table.cellAt (rownr + 1, colnr).firstCursorPosition ()
cellCursor.setBlockFormat (cellBlockFormat)
cellCursor.insertText (str (col))
#footer
painter.begin(printer)
painter.drawText (0, pageRect.bottom(), "I may be the footer")
painter.end()
# section finished
cursor.setPosition (mainFrame.lastPosition ())
tableFormat.setPageBreakPolicy (QTextFormat.PageBreak_AlwaysAfter)
cursor.insertBlock (cellBlockFormat, cellCharFormat)
document.print_(printer)
前提:这与其说是一种解决方案,不如说是一种黑客攻击,因为它是一种肮脏的解决方法。
想法是子类化 QPrinter,覆盖 newPage
方法并相应地绘制页脚。这需要使用页脚手动更新 printer
实例。
不幸的是,还有一个重要问题:只要只有一页,我就无法打印页脚。
过几天我再研究一下,看看有没有解决办法。
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtPrintSupport import *
class FooterPrinter(QPrinter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.footers = {}
def paintEngine(self, *args):
engine = super().paintEngine(*args)
self.currentPage = 0
return engine
def drawFooter(self):
text = self.footers.get(self.currentPage)
if not text:
return
painter = super().paintEngine().painter()
dpiy = painter.device().logicalDpiY()
margin = dpiy * (2/2.54)
rect = QRectF(margin, margin, self.width() - margin * 2, self.height() - margin * 2)
fm = QFontMetrics(painter.font(), painter.device())
size = fm.size(0, text)
painter.drawText(rect.left(), rect.bottom() - size.height(),
size.width(), size.height(), Qt.AlignLeft|Qt.AlignTop, text)
def newPage(self):
self.drawFooter()
newPage = super().newPage()
if newPage:
self.currentPage += 1
self.drawFooter()
return newPage
content = [['section 1', [1,2,3,4]],['section2', [5,6,7,8]]]
app = QApplication(sys.argv)
document = QTextDocument()
printer = FooterPrinter()
printer.setOutputFileName('/tmp/test.pdf')
pageRect = printer.pageRect ()
tableFormat = QTextTableFormat ()
cellBlockFormat = QTextBlockFormat ()
cellCharFormat = QTextCharFormat ()
cellCharFormat.setFont (QFont ("Arial", 10))
for rownr, line in enumerate(content):
cursor = QTextCursor (document)
mainFrame = cursor.currentFrame ()
# header
cursor.setPosition (mainFrame.firstPosition ())
cursor.insertHtml ("This is the table for %s"%line[0])
# table
table = cursor.insertTable (3, 4, tableFormat)
for colnr, col in enumerate(line[1]):
cellCursor = table.cellAt (rownr + 1, colnr).firstCursorPosition ()
cellCursor.setBlockFormat (cellBlockFormat)
cellCursor.insertText (str (col))
cursor.setPosition (mainFrame.lastPosition ())
tableFormat.setPageBreakPolicy (QTextFormat.PageBreak_AlwaysAfter)
cursor.insertBlock (cellBlockFormat, cellCharFormat)
printer.footers[rownr] = 'Note for page {}: some text.\nNew line\nAnother new line'.format(rownr + 1)
document.print_(printer)