Python 3.x 如何正确设置打印机的油漆工?
我正在打印一组表格,每个表格都应该有自己的页面,并且可能很长。基本的工作,但我没有得到的页脚画。问题是页脚将被绘制在额外的文档中 根据文件,我必须将油漆工设置到设备上。设备是painter,这是正确的,但是如何将painter设置为正确的块?还是这样做是错误的 目标是两次使用此文档。第一次尝试是打印,第二次尝试是打印一个Python 3.x 如何正确设置打印机的油漆工?,python-3.x,pyqt5,qpainter,qprinter,qtextdocument,Python 3.x,Pyqt5,Qpainter,Qprinter,Qtextdocument,我正在打印一组表格,每个表格都应该有自己的页面,并且可能很长。基本的工作,但我没有得到的页脚画。问题是页脚将被绘制在额外的文档中 根据文件,我必须将油漆工设置到设备上。设备是painter,这是正确的,但是如何将painter设置为正确的块?还是这样做是错误的 目标是两次使用此文档。第一次尝试是打印,第二次尝试是打印一个QTextDocument,在这里我可以看到QTextTable,并用另一个文档元素编译它 工作示例 import sys from PyQt5.QtWidgets import
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
方法并相应地绘制页脚。这要求使用页脚手动更新打印机
实例
不幸的是,还有一个重要的问题:只要只有一页,我就无法打印页脚
在接下来的几天里,我将尝试再次调查,并找出是否有解决方案
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)
你能澄清最后一段吗?我指的是“在那里我可以绘制QTextTable并用另一个文档元素编译它”。在打印时更改文档结构不是一个好主意。我从DOC的“代码”> QText文档的理解是结构化的富文本文档的容器,我可以通过<代码>访问<代码>文档元素< /C> >,可以使用QText光标编程编辑QText文档。可以通过遍历文档结构来检查其内容。如中所述。因此,我的想法是构建诸如frontpage、序言、目录、列表、报告表之类的元素,并将它们存储在
QTextBlock、QTextFrame、QTextTable和QTextList
类中,这些类可以通过insertBlock()
插入。我理解错了吗?基本上,我正在努力混合绘画元素和文本块。你必须明白,“绘画”总是相对结构化格式的绝对和最终结果。如果你想在打印时添加元素,你不能依赖自动的print
方法,因为它已经绘制了整个文档,所以你需要通过扩展drawContents
的功能来手动实现绘制。感谢澄清,这意味着我必须创建和收集块(文本块、框架、表格等),在列表中,例如,计算文本长度,除以pageRect长度,然后我可以绘制页脚,然后绘制页面,如其他一些问题所示。听起来很复杂。特别是对于内容列表,如果其结果超过1页。老实说,我不能相信这一点,因为这或多或少是一种标准行为,应该在更容易的事情上得到支持。在我看来,把Qprinter
分卡是个好主意。关于单个页面,可能另一个包含空页面并在之后删除的黑客会有所帮助。我下几天无法处理,将尽快继续。但我不认为这是一个肮脏的黑客行为,更像是一个天才的解决方案。不幸的是,你不能在事后删除页面(如果不是使用外部工具的话),因为只要print
返回,文件就已经被写入并关闭(这也意味着你不能在事后调用newPage()
)。另外,print\uuu
所做的几乎所有事情都是私有的,我很“幸运”,因为我意识到paintEngine
和newPage
都是显式调用的。我的解决方法是,如果超过1页,就决定使用上面的类,并且只对1页使用第一个解决方案。虽然不完美,但它确实有效。