打印时不考虑HTMLtable长宽
The HTML table length and width is not taken in consideration when printing
使用 Pyside6
,我正在尝试打印 HTML Table。 HTML table 格式在浏览器中看起来不错。但是,当我在 Pyside6 的打印预览中打开它时,不考虑 table 的长度和宽度并且 table 折叠。
开发环境:
- Ubuntu 20.04
- Python 3.8.10(使用python虚拟环境)
- PySide6 版本 6.1.3
我也在 Windows 中用 Python 3.9.7 和 Pyside6 版本 6.2 尝试了相同的代码,得到了相同的结果。
预期:
实际:
main.py
from PySide6.QtGui import (
QPageSize,
QPageLayout,
QTextBlockFormat,
QTextCursor,
QTextDocument,
QTextFormat,
)
from PySide6.QtWidgets import QApplication
from PySide6.QtPrintSupport import QPrinter, QPrintPreviewDialog
app = QApplication()
dialog = QPrintPreviewDialog()
def handle_paint_requested(printer):
document = QTextDocument()
f = open("template.html", "r")
billTemplate = f.read()
document.setHtml(billTemplate)
document.print_(printer)
dialog.paintRequested.connect(handle_paint_requested)
dialog.exec()
template.html
<p> </p>
<table style="border-collapse: collapse; width: 300px;" border="1">
<tbody>
<tr>
<td style="width: 50%; height: 50px;">test1</td>
<td style="width: 50%; height: 50px;"> </td>
</tr>
</tbody>
</table>
由于 QTextDocument 仅支持 HTML4 属性的子集,因此会导致观察到的错误。
一种解决方法是使用在 Qt 6.2 中重新引入的 QtWebEngine。目前只有 windows .whl 在 pypi 中可用(请参阅 here and here 了解更多信息)因此我们可以安装 Linux 和 MacOs 包,您必须执行:
python -m pip install pyside6 \
--index-url=http://download.qt.io/official_releases/QtForPython
所以将 翻译成 PySide6:
import os
from pathlib import Path
from PySide6.QtCore import (
QCoreApplication,
QEventLoop,
QObject,
QPointF,
Qt,
QUrl,
Slot,
)
from PySide6.QtGui import QKeySequence, QPainter, QShortcut
from PySide6.QtPrintSupport import QPrintDialog, QPrinter, QPrintPreviewDialog
from PySide6.QtWebEngineWidgets import QWebEngineView
from PySide6.QtWidgets import (
QApplication,
QDialog,
QProgressBar,
QProgressDialog,
)
CURRENT_DIRECTORY = Path(__file__).resolve().parent
class PrintHandler(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.m_page = None
self.m_inPrintPreview = False
def setPage(self, page):
assert not self.m_page
self.m_page = page
self.m_page.printRequested.connect(self.printPreview)
@Slot()
def print(self):
printer = QPrinter(QPrinter.HighResolution)
dialog = QPrintDialog(printer, QWebEngineView.forPage(self.m_page))
if dialog.exec_() != QDialog.Accepted:
return
self.printDocument(printer)
@Slot()
def printPreview(self):
if not self.m_page:
return
if self.m_inPrintPreview:
return
self.m_inPrintPreview = True
printer = QPrinter()
preview = QPrintPreviewDialog(printer, QWebEngineView.forPage(self.m_page))
preview.paintRequested.connect(self.printDocument)
preview.exec()
self.m_inPrintPreview = False
@Slot(QPrinter)
def printDocument(self, printer):
loop = QEventLoop()
result = False
def printPreview(success):
nonlocal result
result = success
loop.quit()
view = QWebEngineView.forPage(self.m_page)
view.printFinished.connect(printPreview)
progressbar = QProgressDialog(view)
progressbar.findChild(QProgressBar).setTextVisible(False)
progressbar.setLabelText("Wait please...")
progressbar.setRange(0, 0)
progressbar.show()
progressbar.canceled.connect(loop.quit)
view.print(printer)
loop.exec()
progressbar.close()
if not result:
painter = QPainter()
if painter.begin(printer):
font = painter.font()
font.setPixelSize(20)
painter.setFont(font)
painter.drawText(QPointF(10, 25), "Could not generate print preview.")
painter.end()
def main():
import sys
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv)
app.setApplicationName("Previewer")
filename = CURRENT_DIRECTORY / "template.html"
url = QUrl.fromLocalFile(os.fspath(filename))
view = QWebEngineView()
view.setUrl(url)
view.resize(1024, 750)
view.show()
handler = PrintHandler()
handler.setPage(view.page())
printPreviewShortCut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P), view)
printShortCut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_P), view)
printPreviewShortCut.activated.connect(handler.printPreview)
printShortCut.activated.connect(handler.print)
sys.exit(app.exec())
if __name__ == "__main__":
main()
在按下 Ctrl + P 后你得到:
使用 Pyside6
,我正在尝试打印 HTML Table。 HTML table 格式在浏览器中看起来不错。但是,当我在 Pyside6 的打印预览中打开它时,不考虑 table 的长度和宽度并且 table 折叠。
开发环境:
- Ubuntu 20.04
- Python 3.8.10(使用python虚拟环境)
- PySide6 版本 6.1.3
我也在 Windows 中用 Python 3.9.7 和 Pyside6 版本 6.2 尝试了相同的代码,得到了相同的结果。
预期:
实际:
main.py
from PySide6.QtGui import (
QPageSize,
QPageLayout,
QTextBlockFormat,
QTextCursor,
QTextDocument,
QTextFormat,
)
from PySide6.QtWidgets import QApplication
from PySide6.QtPrintSupport import QPrinter, QPrintPreviewDialog
app = QApplication()
dialog = QPrintPreviewDialog()
def handle_paint_requested(printer):
document = QTextDocument()
f = open("template.html", "r")
billTemplate = f.read()
document.setHtml(billTemplate)
document.print_(printer)
dialog.paintRequested.connect(handle_paint_requested)
dialog.exec()
template.html
<p> </p>
<table style="border-collapse: collapse; width: 300px;" border="1">
<tbody>
<tr>
<td style="width: 50%; height: 50px;">test1</td>
<td style="width: 50%; height: 50px;"> </td>
</tr>
</tbody>
</table>
由于 QTextDocument 仅支持 HTML4 属性的子集,因此会导致观察到的错误。
一种解决方法是使用在 Qt 6.2 中重新引入的 QtWebEngine。目前只有 windows .whl 在 pypi 中可用(请参阅 here and here 了解更多信息)因此我们可以安装 Linux 和 MacOs 包,您必须执行:
python -m pip install pyside6 \
--index-url=http://download.qt.io/official_releases/QtForPython
所以将
import os
from pathlib import Path
from PySide6.QtCore import (
QCoreApplication,
QEventLoop,
QObject,
QPointF,
Qt,
QUrl,
Slot,
)
from PySide6.QtGui import QKeySequence, QPainter, QShortcut
from PySide6.QtPrintSupport import QPrintDialog, QPrinter, QPrintPreviewDialog
from PySide6.QtWebEngineWidgets import QWebEngineView
from PySide6.QtWidgets import (
QApplication,
QDialog,
QProgressBar,
QProgressDialog,
)
CURRENT_DIRECTORY = Path(__file__).resolve().parent
class PrintHandler(QObject):
def __init__(self, parent=None):
super().__init__(parent)
self.m_page = None
self.m_inPrintPreview = False
def setPage(self, page):
assert not self.m_page
self.m_page = page
self.m_page.printRequested.connect(self.printPreview)
@Slot()
def print(self):
printer = QPrinter(QPrinter.HighResolution)
dialog = QPrintDialog(printer, QWebEngineView.forPage(self.m_page))
if dialog.exec_() != QDialog.Accepted:
return
self.printDocument(printer)
@Slot()
def printPreview(self):
if not self.m_page:
return
if self.m_inPrintPreview:
return
self.m_inPrintPreview = True
printer = QPrinter()
preview = QPrintPreviewDialog(printer, QWebEngineView.forPage(self.m_page))
preview.paintRequested.connect(self.printDocument)
preview.exec()
self.m_inPrintPreview = False
@Slot(QPrinter)
def printDocument(self, printer):
loop = QEventLoop()
result = False
def printPreview(success):
nonlocal result
result = success
loop.quit()
view = QWebEngineView.forPage(self.m_page)
view.printFinished.connect(printPreview)
progressbar = QProgressDialog(view)
progressbar.findChild(QProgressBar).setTextVisible(False)
progressbar.setLabelText("Wait please...")
progressbar.setRange(0, 0)
progressbar.show()
progressbar.canceled.connect(loop.quit)
view.print(printer)
loop.exec()
progressbar.close()
if not result:
painter = QPainter()
if painter.begin(printer):
font = painter.font()
font.setPixelSize(20)
painter.setFont(font)
painter.drawText(QPointF(10, 25), "Could not generate print preview.")
painter.end()
def main():
import sys
QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication(sys.argv)
app.setApplicationName("Previewer")
filename = CURRENT_DIRECTORY / "template.html"
url = QUrl.fromLocalFile(os.fspath(filename))
view = QWebEngineView()
view.setUrl(url)
view.resize(1024, 750)
view.show()
handler = PrintHandler()
handler.setPage(view.page())
printPreviewShortCut = QShortcut(QKeySequence(Qt.CTRL + Qt.Key_P), view)
printShortCut = QShortcut(QKeySequence(Qt.CTRL + Qt.SHIFT + Qt.Key_P), view)
printPreviewShortCut.activated.connect(handler.printPreview)
printShortCut.activated.connect(handler.print)
sys.exit(app.exec())
if __name__ == "__main__":
main()
在按下 Ctrl + P 后你得到: