首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在QPdfWriter上组合QPainter和QTextDocument

在QPdfWriter上组合QPainter和QTextDocument
EN

Stack Overflow用户
提问于 2021-08-15 15:27:26
回答 2查看 112关注 0票数 0

在另一个问题中,我了解了QTextDocument,我was told说你可以在同一页上使用QPainterQTextDocument。但是,当我尝试这样做时,它们各自重新启动文档,擦除对方的内容。

代码语言:javascript
复制
from PySide6.QtGui import QPdfWriter, QPainter, QPageSize, QTextDocument, Qt
from PySide6.QtWidgets import QApplication


def main():
    app = QApplication()
    pdf = QPdfWriter('example.pdf')
    pdf.setPageSize(QPageSize.Letter)

    # Whichever of these goes second, overwrites the first.
    draw_diagram(pdf)
    print_document(pdf)

    app.exit(0)


def draw_diagram(pdf: QPdfWriter):
    painter = QPainter(pdf)
    painter.drawArc(painter.window().width()//4,
                    painter.window().height()//2 - painter.window().width()//4,
                    painter.window().width()//2,
                    painter.window().width()//2,
                    0,
                    5760)
    painter.drawText(0,
                     painter.window().height()//2,
                     painter.window().width(),
                     painter.window().height()//10,
                     Qt.AlignHCenter | Qt.AlignTop,
                     'https://donkirkby.github.io')
    print(pdf.newPage())
    painter.drawText(painter.window().width()//2,
                     painter.window().height()//2,
                     'Bar')
    print(pdf.newPage())
    painter.end()


def print_document(pdf: QPdfWriter):
    html = "<a href='https://donkirkby.github.io'>donkirkby.github.io</a>"

    document = QTextDocument()
    document.setHtml(html)
    document.print_(pdf)


main()

理想情况下,我希望文本和绘图在同一页上,但是这段代码试图将它们分开,这样它们就不会相互覆盖。这两种方式都不起作用。

如何将图形与文本文档合并?QTextCursor有帮助吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-08-15 17:16:30

问题是,每次设置QPainter时,QPdfWriter都会被重置。一种可能的解决方案是使用相同的QPainter,而不是应该使用drawContents的print方法,您还必须手动处理分页。

代码语言:javascript
复制
from PySide6.QtGui import QPdfWriter, QPainter, QPageSize, QTextDocument, Qt
from PySide6.QtWidgets import QApplication


def main():
    app = QApplication()
    pdf = QPdfWriter("example.pdf")
    pdf.setPageSize(QPageSize.Letter)

    painter = QPainter(pdf)

    draw_diagram(painter, pdf)
    print_document(painter, pdf)

    painter.end()


def draw_diagram(painter: QPainter, pdf: QPdfWriter):
    painter.drawArc(
        painter.window().width() // 4,
        painter.window().height() // 2 - painter.window().width() // 4,
        painter.window().width() // 2,
        painter.window().width() // 2,
        0,
        5760,
    )
    painter.drawText(
        0,
        painter.window().height() // 2,
        painter.window().width(),
        painter.window().height() // 10,
        Qt.AlignHCenter | Qt.AlignTop,
        "https://donkirkby.github.io",
    )
    print(pdf.newPage())
    painter.drawText(
        painter.window().width() // 2, painter.window().height() // 2, "Bar"
    )
    print(pdf.newPage())


def print_document(painter: QPainter, pdf: QPdfWriter):
    document = QTextDocument()
    document.documentLayout().setPaintDevice(pdf)

    html = "<a href='https://donkirkby.github.io'>donkirkby.github.io</a>"
    document.setHtml(html)

    document.drawContents(painter)


if __name__ == "__main__":
    main()
票数 2
EN

Stack Overflow用户

发布于 2021-08-15 22:37:12

虽然我最终使用了从document.print_()切换到document.drawContents()eyllanesc's answer,但我也尝试了QTextCursorQPyTextObject。这个TextObject example给出了一个很好的介绍。我想,如果我需要跨多个页面,它会很有用。

下面是转换为使用QPyTextObject的问题的示例

代码语言:javascript
复制
from PySide6.QtCore import QSizeF, QRectF
from PySide6.QtGui import (QPdfWriter, QPainter, QPageSize, QTextDocument, Qt, QPyTextObject, QTextFormat, QTextCursor,
                           QTextCharFormat)
from PySide6.QtWidgets import QApplication

DIAGRAM_TEXT_FORMAT = QTextFormat.UserObject + 1
DIAGRAM_DATA = 1
OBJECT_REPLACEMENT = chr(0xfffc)


def main():
    app = QApplication()
    pdf = QPdfWriter('example.pdf')
    pdf.setPageSize(QPageSize.Letter)

    print_document(pdf)

    app.exit(0)


class Diagram(QPyTextObject):
    def __init__(self, parent=None):
        super().__init__(parent)

    # noinspection PyPep8Naming,PyShadowingBuiltins
    def intrinsicSize(self,
                      doc: QTextDocument,
                      posInDocument: int,
                      format: QTextFormat) -> QSizeF:
        diameter = doc.textWidth()/4
        return QSizeF(doc.textWidth(), diameter)

    # noinspection PyPep8Naming,PyShadowingBuiltins
    def drawObject(self,
                   painter: QPainter,
                   rect: QRectF,
                   doc: QTextDocument,
                   posInDocument: int,
                   format: QTextFormat):
        diameter = rect.height()
        message = format.property(DIAGRAM_DATA)
        painter.drawArc((rect.width() - diameter) // 2,
                        rect.y(),
                        diameter,
                        diameter,
                        0,
                        5760)
        painter.drawText(rect,
                         Qt.AlignHCenter | Qt.AlignVCenter,
                         message)


def print_document(pdf: QPdfWriter):
    html = """\
<h1>Title</h1>
<p>Lorem ipsum
<a href='https://donkirkby.github.io'>donkirkby.github.io</a>
dolores sit amet.</p>
"""

    document = QTextDocument()
    document.setPageSize(QSizeF(pdf.width(), pdf.height()))
    font = document.defaultFont()
    font.setPixelSize(pdf.height()//60)
    document.setDefaultFont(font)
    diagram_handler = Diagram()
    doc_layout = document.documentLayout()
    doc_layout.registerHandler(DIAGRAM_TEXT_FORMAT, diagram_handler)

    document.setHtml(html)
    cursor = QTextCursor(document)
    cursor.movePosition(cursor.End)
    cursor.insertText('\n')
    
    diagram_format = QTextCharFormat()
    diagram_format.setObjectType(DIAGRAM_TEXT_FORMAT)

    for i in range(1, 11):
        cursor.insertHtml(f'<h3>Heading {i}</h3>')
        cursor.insertText('\n')
        diagram_format.setProperty(DIAGRAM_DATA, f'Message {i} in a circle')
        cursor.insertText(OBJECT_REPLACEMENT, diagram_format)

    document.print_(pdf)


main()

我仍然不喜欢这种方法的一点是,可以在标题和图表之间添加分页符。我会问一个关于这个问题的后续问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68792928

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档