Как при печати таблицы из QTableWidget задать размер колонок и изменить их внешний вид

Я отправляю на печать таблицу созданную из QTableWidget и заголовок к ней, который почему-то появляется снизу.

Подскажите, можно ли как то установить заголовок на самый вверх документа, далее пропустить строчку и после этого только выводить таблицу.
А также, можно ли как то изменить вид рамок таблицы и изменять размер столбцов при печати, т.к. они всегда подгоняются под размер содержимого или подскажите куда двигаться.

from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from PyQt5.QtGui import QFont
from PyQt5.QtPrintSupport import QPrinter


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(519, 447)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(40, 70, 431, 241))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.tableWidget.setFont(font)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(3)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(2, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(0, 0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(0, 1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(1, 0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(1, 1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(2, 0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(2, 1, item)
        self.tableWidget.horizontalHeader().setMinimumSectionSize(62)
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(40, 340, 431, 51))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(170, 30, 181, 31))
        font = QtGui.QFont()
        font.setPointSize(13)
        self.label.setFont(font)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        item = self.tableWidget.verticalHeaderItem(0)
        item.setText(_translate("MainWindow", "1"))
        item = self.tableWidget.verticalHeaderItem(1)
        item.setText(_translate("MainWindow", "2"))
        item = self.tableWidget.verticalHeaderItem(2)
        item.setText(_translate("MainWindow", "3"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "Column 1"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "Column 2"))
        __sortingEnabled = self.tableWidget.isSortingEnabled()
        self.tableWidget.setSortingEnabled(False)
        item = self.tableWidget.item(0, 0)
        item.setText(_translate("MainWindow", "Test row 1 col 1"))
        item = self.tableWidget.item(0, 1)
        item.setText(_translate("MainWindow", "Test row 1 col 2"))
        item = self.tableWidget.item(1, 0)
        item.setText(_translate("MainWindow", "Test row 2 col 1"))
        item = self.tableWidget.item(1, 1)
        item.setText(_translate("MainWindow", "Test row 2 col 2"))
        item = self.tableWidget.item(2, 0)
        item.setText(_translate("MainWindow", "Test row 3 col 1"))
        item = self.tableWidget.item(2, 1)
        item.setText(_translate("MainWindow", "Test row 3 col 2"))
        self.tableWidget.setSortingEnabled(__sortingEnabled)
        self.pushButton.setText(_translate("MainWindow", "Preview/Print"))
        self.label.setText(_translate("MainWindow", "Print Table Widget"))


class PrintTableWidget(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # делаем ресайз колонок
        self.tableWidget.horizontalHeader().setDefaultSectionSize(200)
        self.pushButton.clicked.connect(self.handlePreview)


    def handlePrint(self):
        dialog = QtPrintSupport.QPrintDialog()
        if dialog.exec_() == QtWidgets.QDialog.Accepted:
            printer = QPrinter(QPrinter.HighResolution)
            printer.setPaperSize(QPrinter.A4)
            self.handlePaintRequest(dialog.printer())

    def handlePreview(self):
        dialog = QtPrintSupport.QPrintPreviewDialog()
        dialog.paintRequested.connect(self.handlePaintRequest)
        dialog.exec_()

    def handlePaintRequest(self, printer):
        document = QtGui.QTextDocument()
        document.setPlainText("Заголовок") # <-- нужно перенести наверх как заголовок
        # устанавливаем размер текста по умолчанию
        font = QFont('Arial', 18)
        document.setDefaultFont(font)
        cursor = QtGui.QTextCursor(document)
        table = cursor.insertTable(self.tableWidget.rowCount(), self.tableWidget.columnCount())
        for row in range(table.rows()):
            for col in range(table.columns()):
                it = self.tableWidget.item(row, col)
                if it is not None:
                    cursor.insertText(it.text())
                cursor.movePosition(QtGui.QTextCursor.NextCell)
        document.print_(printer)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ptw = PrintTableWidget()
    ptw.show()
    sys.exit(app.exec_()) 

введите сюда описание изображения


Ответы (1 шт):

Автор решения: S. Nick

Попробуйте insertHtml.

void QTextCursor::insertHtml(const QString &html)

Вставляет текст html в текущую position().

Текст интерпретируется как HTML. Примечание. При использовании этой функции с таблицей стилей таблица стилей будет применяться только к текущему блоку в документе. Чтобы применить таблицу стилей ко всему документу, используйте вместо нее QTextDocument::setDefaultStyleSheet().

https://doc.qt.io/qt-5/qtextcursor.html#insertHtml


from PyQt5 import QtCore, QtGui, QtWidgets, QtPrintSupport
from PyQt5.QtGui import QFont
from PyQt5.QtPrintSupport import QPrinter


class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(519, 447)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.tableWidget = QtWidgets.QTableWidget(self.centralwidget)
        self.tableWidget.setGeometry(QtCore.QRect(40, 70, 431, 241))
        font = QtGui.QFont()
        font.setPointSize(15)
        self.tableWidget.setFont(font)
        self.tableWidget.setObjectName("tableWidget")
        self.tableWidget.setColumnCount(2)
        self.tableWidget.setRowCount(3)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setVerticalHeaderItem(2, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setHorizontalHeaderItem(1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(0, 0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(0, 1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(1, 0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(1, 1, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(2, 0, item)
        item = QtWidgets.QTableWidgetItem()
        self.tableWidget.setItem(2, 1, item)
        self.tableWidget.horizontalHeader().setMinimumSectionSize(62)
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setGeometry(QtCore.QRect(40, 340, 431, 51))
        font = QtGui.QFont()
        font.setPointSize(16)
        self.pushButton.setFont(font)
        self.pushButton.setObjectName("pushButton")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(170, 30, 181, 31))
        font = QtGui.QFont()
        font.setPointSize(13)
        self.label.setFont(font)
        self.label.setObjectName("label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        item = self.tableWidget.verticalHeaderItem(0)
        item.setText(_translate("MainWindow", "1"))
        item = self.tableWidget.verticalHeaderItem(1)
        item.setText(_translate("MainWindow", "2"))
        item = self.tableWidget.verticalHeaderItem(2)
        item.setText(_translate("MainWindow", "3"))
        item = self.tableWidget.horizontalHeaderItem(0)
        item.setText(_translate("MainWindow", "Column 1"))
        item = self.tableWidget.horizontalHeaderItem(1)
        item.setText(_translate("MainWindow", "Column 2"))
        __sortingEnabled = self.tableWidget.isSortingEnabled()
        self.tableWidget.setSortingEnabled(False)
        item = self.tableWidget.item(0, 0)
        item.setText(_translate("MainWindow", "Test row 1 col 1"))
        item = self.tableWidget.item(0, 1)
        item.setText(_translate("MainWindow", "Test row 1 col 2"))
        item = self.tableWidget.item(1, 0)
        item.setText(_translate("MainWindow", "Test row 2 col 1"))
        item = self.tableWidget.item(1, 1)
        item.setText(_translate("MainWindow", "Test row 2 col 2"))
        item = self.tableWidget.item(2, 0)
        item.setText(_translate("MainWindow", "Test row 3 col 1"))
        item = self.tableWidget.item(2, 1)
        item.setText(_translate("MainWindow", "Test row 3 col 2"))
        self.tableWidget.setSortingEnabled(__sortingEnabled)
        self.pushButton.setText(_translate("MainWindow", "Preview/Print"))
        self.label.setText(_translate("MainWindow", "Print Table Widget"))


class PrintTableWidget(QtWidgets.QMainWindow, Ui_MainWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        # делаем ресайз колонок
        self.tableWidget.horizontalHeader().setDefaultSectionSize(200)
        self.pushButton.clicked.connect(self.handlePreview)

    def handlePrint(self):
        dialog = QtPrintSupport.QPrintDialog()
        if dialog.exec_() == QtWidgets.QDialog.Accepted:
            printer = QPrinter(QPrinter.HighResolution)
            printer.setPaperSize(QPrinter.A4)
            self.handlePaintRequest(dialog.printer())

    def handlePreview(self):
        dialog = QtPrintSupport.QPrintPreviewDialog()
        dialog.paintRequested.connect(self.handlePaintRequest)
        dialog.exec_()

    def handlePaintRequest(self, printer):
        document = QtGui.QTextDocument()
#        document.setPlainText("Заголовок") # <-- нужно перенести наверх как заголовок
        # устанавливаем размер текста по умолчанию
#        font = QFont('Arial', 18)
        font = QFont('Arial', 27)
        document.setDefaultFont(font)
        cursor = QtGui.QTextCursor(document)

# +++          vvvvvvvvvv
        cursor.insertHtml('<h2 align="center" style="color: red;" >Заголовок<br></h2>')
        
        table = cursor.insertTable(self.tableWidget.rowCount(), 
                                   self.tableWidget.columnCount())
        for row in range(table.rows()):
            for col in range(table.columns()):
                it = self.tableWidget.item(row, col)
                if it is not None:

#                    cursor.insertText(it.text())
# +++                      vvvvvvvvvv
                    cursor.insertHtml(
                        f'<span style="color: blue;"><br>&nbsp;&nbsp;'
                        f'{it.text()}&nbsp;&nbsp;<br></span>')

                cursor.movePosition(QtGui.QTextCursor.NextCell)
        document.print_(printer)


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    ptw = PrintTableWidget()
    ptw.show()
    sys.exit(app.exec_()) 

введите сюда описание изображения

→ Ссылка