pyqt5打印html支持css,python3+PyQt5实现文档打印功能

这篇文章主要为大家详细介绍了python3+PyQt5实现文档打印功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文通过Python3+PyQt5实现《python Qt Gui 快速编程》这本书13章文档打印功能。本文共通过三种方式:

1、使用HTML和QTextDOcument打印文档

2、使用QTextCusor和QTextDocument打印文档

3、使用QPainter打印文档

使用Qpainter打印文档比QTextDocument需要更操心和复杂的计算,但是QPainter确实能够对输出赋予完全控制。

#!/usr/bin/env python3

import math

import sys

import html

from PyQt5.QtPrintSupport import QPrinter,QPrintDialog

from PyQt5.QtCore import (QDate, QRectF, Qt)

from PyQt5.QtWidgets import (QApplication,QDialog,

QHBoxLayout,QPushButton, QTableWidget, QTableWidgetItem,QVBoxLayout)

from PyQt5.QtGui import (QFont,QFontMetrics,QPainter,QTextCharFormat,

QTextCursor, QTextDocument, QTextFormat,

QTextOption, QTextTableFormat,

QPixmap,QTextBlockFormat)

import qrc_resources

from PyQt5.QtPrintSupport import QPrinter,QPrintDialog

from PyQt5.QtCore import (QDate, QRectF, Qt)

from PyQt5.QtWidgets import (QApplication,QDialog,

QHBoxLayout,QPushButton, QTableWidget, QTableWidgetItem,QVBoxLayout)

from PyQt5.QtGui import (QFont,QFontMetrics,QPainter,QTextCharFormat,

QTextCursor, QTextDocument, QTextFormat,

QTextOption, QTextTableFormat,

QPixmap,QTextBlockFormat)

import qrc_resources

DATE_FORMAT = "MMM d, yyyy"

class Statement(object):

def __init__(self, company, contact, address):

self.company = company

self.contact = contact

self.address = address

self.transactions = [] # List of (QDate, float) two-tuples

def balance(self):

return sum([amount for date, amount in self.transactions])

class Form(QDialog):

def __init__(self, parent=None):

super(Form, self).__init__(parent)

self.printer = QPrinter()

self.printer.setPageSize(QPrinter.Letter)

self.generateFakeStatements()

self.table = QTableWidget()

self.populateTable()

cursorButton = QPushButton("Print via Q&Cursor")

htmlButton = QPushButton("Print via &HTML")

painterButton = QPushButton("Print via Q&Painter")

quitButton = QPushButton("&Quit")

buttonLayout = QHBoxLayout()

buttonLayout.addWidget(cursorButton)

buttonLayout.addWidget(htmlButton)

buttonLayout.addWidget(painterButton)

buttonLayout.addStretch()

buttonLayout.addWidget(quitButton)

layout = QVBoxLayout()

layout.addWidget(self.table)

layout.addLayout(buttonLayout)

self.setLayout(layout)

cursorButton.clicked.connect(self.printViaQCursor)

htmlButton.clicked.connect(self.printViaHtml)

painterButton.clicked.connect(self.printViaQPainter)

quitButton.clicked.connect(self.accept)

self.setWindowTitle("Printing")

def generateFakeStatements(self):

self.statements = []

statement = Statement("Consality", "Ms S. Royal",

"234 Rue Saint Hyacinthe, 750201, Paris")

statement.transactions.append((QDate(2007, 8, 11), 2342))

statement.transactions.append((QDate(2007, 9, 10), 2342))

statement.transactions.append((QDate(2007, 10, 9), 2352))

statement.transactions.append((QDate(2007, 10, 17), -1500))

statement.transactions.append((QDate(2007, 11, 12), 2352))

statement.transactions.append((QDate(2007, 12, 10), 2352))

statement.transactions.append((QDate(2007, 12, 20), -7500))

statement.transactions.append((QDate(2007, 12, 20), 250))

statement.transactions.append((QDate(2008, 1, 10), 2362))

self.statements.append(statement)

statement = Statement("Demamitur Plc", "Mr G. Brown",

"14 Tall Towers, Tower Hamlets, London, WC1 3BX")

statement.transactions.append((QDate(2007, 5, 21), 871))

statement.transactions.append((QDate(2007, 6, 20), 542))

statement.transactions.append((QDate(2007, 7, 20), 1123))

statement.transactions.append((QDate(2007, 7, 20), -1928))

statement.transactions.append((QDate(2007, 8, 13), -214))

statement.transactions.append((QDate(2007, 9, 15), -3924))

statement.transactions.append((QDate(2007, 9, 15), 2712))

statement.transactions.append((QDate(2007, 9, 15), -273))

#statement.transactions.append((QDate(2007, 11, 8), -728))

#statement.transactions.append((QDate(2008, 2, 7), 228))

#statement.transactions.append((QDate(2008, 3, 13), -508))

#statement.transactions.append((QDate(2008, 3, 22), -2481))

#statement.transactions.append((QDate(2008, 4, 5), 195))

self.statements.append(statement)

def populateTable(self):

headers = ["Company", "Contact", "Address", "Balance"]

self.table.setColumnCount(len(headers))

self.table.setHorizontalHeaderLabels(headers)

self.table.setRowCount(len(self.statements))

for row, statement in enumerate(self.statements):

self.table.setItem(row, 0, QTableWidgetItem(statement.company))

self.table.setItem(row, 1, QTableWidgetItem(statement.contact))

self.table.setItem(row, 2, QTableWidgetItem(statement.address))

item = QTableWidgetItem("$ {0:,.2f}".format(float(statement.balance())))

item.setTextAlignment(Qt.AlignRight|Qt.AlignVCenter)

self.table.setItem(row, 3, item)

self.table.resizeColumnsToContents()

def printViaHtml(self):

htmltext = ""

for statement in self.statements:

date = QDate.currentDate().toString(DATE_FORMAT)

address = html.escape(statement.address).replace(

",", "
")

contact = html.escape(statement.contact)

balance = statement.balance()

htmltext += ("

logo.png

"

"

Greasy Hands Ltd."

"
New Lombard Street"

"
London
WC13 4PX
{0}

"

"

{1}

Dear {2},

"

"

The balance of your account is $ {3:,.2f}.").format(

date, address, contact, float(balance))

if balance < 0:

htmltext += ("

Please remit the "

"amount owing immediately.")

else:

htmltext += (" We are delighted to have done business "

"with you.")

htmltext += ("

"

"

"cellspacing=2>

"

"Transactions

")

for date, amount in statement.transactions:

color, status = "black", "Credit"

if amount < 0:

color, status = "red", "Debit"

htmltext += ("

{0}"

"

{1}"

"$ {3:,.2f}

".format(

date.toString(DATE_FORMAT), status, color,float(abs(amount))))

htmltext += ("

"

"We hope to continue doing "

"business with you,
Yours sincerely,"

"
K. Longrey, Manager

")

dialog = QPrintDialog(self.printer, self)

if dialog.exec_():

document = QTextDocument()

document.setHtml(htmltext)

document.print_(self.printer)

def printViaQCursor(self):

dialog = QPrintDialog(self.printer, self)

if not dialog.exec_():

return

logo = QPixmap(":/logo.png")

headFormat = QTextBlockFormat()

headFormat.setAlignment(Qt.AlignLeft)

headFormat.setTextIndent(

self.printer.pageRect().width() - logo.width() - 216)

bodyFormat = QTextBlockFormat()

bodyFormat.setAlignment(Qt.AlignJustify)

lastParaBodyFormat = QTextBlockFormat(bodyFormat)

lastParaBodyFormat.setPageBreakPolicy(

QTextFormat.PageBreak_AlwaysAfter)

rightBodyFormat = QTextBlockFormat()

rightBodyFormat.setAlignment(Qt.AlignRight)

headCharFormat = QTextCharFormat()

headCharFormat.setFont(QFont("Helvetica", 10))

bodyCharFormat = QTextCharFormat()

bodyCharFormat.setFont(QFont("Times", 11))

redBodyCharFormat = QTextCharFormat(bodyCharFormat)

redBodyCharFormat.setForeground(Qt.red)

tableFormat = QTextTableFormat()

tableFormat.setBorder(1)

tableFormat.setCellPadding(2)

document = QTextDocument()

cursor = QTextCursor(document)

mainFrame = cursor.currentFrame()

page = 1

for statement in self.statements:

cursor.insertBlock(headFormat, headCharFormat)

cursor.insertImage(":/logo.png")

for text in ("Greasy Hands Ltd.", "New Lombard Street",

"London", "WC13 4PX",

QDate.currentDate().toString(DATE_FORMAT)):

cursor.insertBlock(headFormat, headCharFormat)

cursor.insertText(text)

for line in statement.address.split(", "):

cursor.insertBlock(bodyFormat, bodyCharFormat)

cursor.insertText(line)

cursor.insertBlock(bodyFormat)

cursor.insertBlock(bodyFormat, bodyCharFormat)

cursor.insertText("Dear {0},".format(statement.contact))

cursor.insertBlock(bodyFormat)

cursor.insertBlock(bodyFormat, bodyCharFormat)

balance = statement.balance()

cursor.insertText("The balance of your account is $ {0:,.2f}.".format(float(balance)))

if balance < 0:

cursor.insertBlock(bodyFormat, redBodyCharFormat)

cursor.insertText("Please remit the amount owing "

"immediately.")

else:

cursor.insertBlock(bodyFormat, bodyCharFormat)

cursor.insertText("We are delighted to have done "

"business with you.")

cursor.insertBlock(bodyFormat, bodyCharFormat)

cursor.insertText("Transactions:")

table = cursor.insertTable(len(statement.transactions), 3,

tableFormat)

row = 0

for date, amount in statement.transactions:

cellCursor = table.cellAt(row, 0).firstCursorPosition()

cellCursor.setBlockFormat(rightBodyFormat)

cellCursor.insertText(date.toString(DATE_FORMAT),

bodyCharFormat)

cellCursor = table.cellAt(row, 1).firstCursorPosition()

if amount > 0:

cellCursor.insertText("Credit", bodyCharFormat)

else:

cellCursor.insertText("Debit", bodyCharFormat)

cellCursor = table.cellAt(row, 2).firstCursorPosition()

cellCursor.setBlockFormat(rightBodyFormat)

format = bodyCharFormat

if amount < 0:

format = redBodyCharFormat

cellCursor.insertText("$ {0:,.2f}".format(float(amount)), format)

row += 1

cursor.setPosition(mainFrame.lastPosition())

cursor.insertBlock(bodyFormat, bodyCharFormat)

cursor.insertText("We hope to continue doing business "

"with you,")

cursor.insertBlock(bodyFormat, bodyCharFormat)

cursor.insertText("Yours sincerely")

cursor.insertBlock(bodyFormat)

if page == len(self.statements):

cursor.insertBlock(bodyFormat, bodyCharFormat)

else:

cursor.insertBlock(lastParaBodyFormat, bodyCharFormat)

cursor.insertText("K. Longrey, Manager")

page += 1

document.print_(self.printer)

def printViaQPainter(self):

dialog = QPrintDialog(self.printer, self)

if not dialog.exec_():

return

LeftMargin = 72

sansFont = QFont("Helvetica", 10)

sansLineHeight = QFontMetrics(sansFont).height()

serifFont = QFont("Times", 11)

fm = QFontMetrics(serifFont)

DateWidth = fm.width(" September 99, 2999 ")

CreditWidth = fm.width(" Credit ")

AmountWidth = fm.width(" W999999.99 ")

serifLineHeight = fm.height()

logo = QPixmap(":/logo.png")

painter = QPainter(self.printer)

pageRect = self.printer.pageRect()

page = 1

for statement in self.statements:

painter.save()

y = 0

x = pageRect.width() - logo.width() - LeftMargin

painter.drawPixmap(x, 0, logo)

y += logo.height() + sansLineHeight

painter.setFont(sansFont)

painter.drawText(x, y, "Greasy Hands Ltd.")

y += sansLineHeight

painter.drawText(x, y, "New Lombard Street")

y += sansLineHeight

painter.drawText(x, y, "London")

y += sansLineHeight

painter.drawText(x, y, "WC13 4PX")

y += sansLineHeight

painter.drawText(x, y,

QDate.currentDate().toString(DATE_FORMAT))

y += sansLineHeight

painter.setFont(serifFont)

x = LeftMargin

for line in statement.address.split(", "):

painter.drawText(x, y, line)

y += serifLineHeight

y += serifLineHeight

painter.drawText(x, y, "Dear {0},".format(statement.contact))

y += serifLineHeight

balance = statement.balance()

painter.drawText(x, y, "The balance of your account is $ {0:,.2f}".format(float(balance)))

y += serifLineHeight

if balance < 0:

painter.setPen(Qt.red)

text = "Please remit the amount owing immediately."

else:

text = ("We are delighted to have done business "

"with you.")

painter.drawText(x, y, text)

painter.setPen(Qt.black)

y += int(serifLineHeight * 1.5)

painter.drawText(x, y, "Transactions:")

y += serifLineHeight

option = QTextOption(Qt.AlignRight|Qt.AlignVCenter)

for date, amount in statement.transactions:

x = LeftMargin

h = int(fm.height() * 1.3)

painter.drawRect(x, y, DateWidth, h)

painter.drawText(

QRectF(x + 3, y + 3, DateWidth - 6, h - 6),

date.toString(DATE_FORMAT), option)

x += DateWidth

painter.drawRect(x, y, CreditWidth, h)

text = "Credit"

if amount < 0:

text = "Debit"

painter.drawText(

QRectF(x + 3, y + 3, CreditWidth - 6, h - 6),

text, option)

x += CreditWidth

painter.drawRect(x, y, AmountWidth, h)

if amount < 0:

painter.setPen(Qt.red)

painter.drawText(

QRectF(x + 3, y + 3, AmountWidth - 6, h - 6),

"$ {0:,.2f}".format(float(amount)),

option)

painter.setPen(Qt.black)

y += h

y += serifLineHeight

x = LeftMargin

painter.drawText(x, y, "We hope to continue doing "

"business with you,")

y += serifLineHeight

painter.drawText(x, y, "Yours sincerely")

y += serifLineHeight * 3

painter.drawText(x, y, "K. Longrey, Manager")

x = LeftMargin

y = pageRect.height() - 72

painter.drawLine(x, y, pageRect.width() - LeftMargin, y)

y += 2

font = QFont("Helvetica", 9)

font.setItalic(True)

painter.setFont(font)

option = QTextOption(Qt.AlignCenter)

option.setWrapMode(QTextOption.WordWrap)

painter.drawText(

QRectF(x, y, pageRect.width() - 2 * LeftMargin, 31),

"The contents of this letter are for information "

"only and do not form part of any contract.",

option)

page += 1

if page <= len(self.statements):

self.printer.newPage()

painter.restore()

if __name__ == "__main__":

app = QApplication(sys.argv)

form = Form()

form.show()

app.exec_()

运行结果:

1b9ee3e210edea07c6c6881fb67e414e.png

相关推荐:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值