如何打印QTableView

5

我有一个使用Python和PySide开发的应用程序,它连接到一个MySQL数据库并在QTableView中显示查询结果。 我需要打印表格视图的内容。 下面是一些代码:

    self.db_table = QtGui.QTableView(self)
    self.model =  QtSql.QSqlQueryModel()
    self.model.setQuery("SELECT * FROM simpsons")
    self.model.setHeaderData(1, QtCore.Qt.Horizontal, self.tr("First Name"))
    self.model.setHeaderData(2, QtCore.Qt.Horizontal, self.tr("Last Name"))
    self.db_table.setModel(self.model) 

    self.print_btn = QtGui.QPushButton("Print")
    self.print_btn.clicked.connect(self.print_btn_clicked)

    def print_btn_clicked(self):
        printDialog = QtGui.QPrintDialog(self.printer, self)
        if printDialog.exec_() == QtGui.QDialog.Accepted:
         #printing code

我找不到此示例,也无法从文档中理解太多,所以我需要一些帮助。


开始阅读Qt文档:http://doc.qt.nokia.com/4.7-snapshot/printing.html - alex vasi
1
谢谢,但我在将C++代码转换为Python时遇到了麻烦。我并不真正了解C++,但Qt文档有时很有帮助。 - Mike Spadaru
4
为什么这个问题被关掉了,但下面的问题却没有受到任何干扰?https://dev59.com/w07Sa4cB1Zd3GeqP6cIY?rq=1 - eric
2个回答

4

实现这个功能的一种方法是将表格内容转储到QTextDocument中,然后打印。

下面的示例使用简单的文本表格,但可以使用html获得更复杂的格式:

from PyQt4 import QtGui, QtCore

class Window(QtGui.QWidget):
    def __init__(self, rows, columns):
        QtGui.QWidget.__init__(self)
        self.table = QtGui.QTableView(self)
        model =  QtGui.QStandardItemModel(rows, columns, self.table)
        for row in range(rows):
            for column in range(columns):
                item = QtGui.QStandardItem('(%d, %d)' % (row, column))
                item.setTextAlignment(QtCore.Qt.AlignCenter)
                model.setItem(row, column, item)
        self.table.setModel(model)
        self.buttonPrint = QtGui.QPushButton('Print', self)
        self.buttonPrint.clicked.connect(self.handlePrint)
        self.buttonPreview = QtGui.QPushButton('Preview', self)
        self.buttonPreview.clicked.connect(self.handlePreview)
        layout = QtGui.QGridLayout(self)
        layout.addWidget(self.table, 0, 0, 1, 2)
        layout.addWidget(self.buttonPrint, 1, 0)
        layout.addWidget(self.buttonPreview, 1, 1)

    def handlePrint(self):
        dialog = QtGui.QPrintDialog()
        if dialog.exec_() == QtGui.QDialog.Accepted:
            self.handlePaintRequest(dialog.printer())

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

    def handlePaintRequest(self, printer):
        document = QtGui.QTextDocument()
        cursor = QtGui.QTextCursor(document)
        model = self.table.model()
        table = cursor.insertTable(
            model.rowCount(), model.columnCount())
        for row in range(table.rows()):
            for column in range(table.columns()):
                cursor.insertText(model.item(row, column).text())
                cursor.movePosition(QtGui.QTextCursor.NextCell)
        document.print_(printer)

if __name__ == '__main__':

    import sys
    app = QtGui.QApplication(sys.argv)
    window = Window(25, 2)
    window.resize(300, 400)
    window.show()
    sys.exit(app.exec_())

感谢ekhumoro和jdi,你们的回答都很好并且有效,但我只能选择一个正确的答案,我会选择ekhumoro的方法,因为他的方法在打印时看起来更好。 - Mike Spadaru

4

当寻找打印多页QTable的方法时,你可能会发现有人建议像@ekhumoro那样将其转换到QTextDocument中或自行管理页面大小并直接从表格打印。

下面是一个简单的例子,展示如何通过自定义打印方法来直接从表格打印:

class Window(QtGui.QDialog):

    def __init__(self):
        ...
        self.db_table = TableView(self)         

    def print_table(self):
        dialog = QtGui.QPrintDialog(self)
        if dialog.exec_() == dialog.Accepted:
            self.db_table.print_(dialog.printer())


class TableView(QtGui.QTableView):

    def print_(self, printer):
        model = self.model()

        rows = model.rowCount()
        cols = model.columnCount()

        totalWidth = 0.0
        for i in xrange(cols):
            totalWidth += self.columnWidth(i)

        painter = QtGui.QPainter(printer)

        pageSize = printer.pageRect()
        pageHeight = pageSize.height()

        scaleX = pageSize.width() / totalWidth
        painter.scale(scaleX, 1.0)

        totalHeight = 0.0 

        newPage = False
        offsetY = 0
        for row in xrange(rows):

            height = self.rowHeight(row)
            totalHeight += height
            if totalHeight > pageHeight:
                totalHeight = height 
                printer.newPage()
                newPage = True 

            for col in xrange(cols):
                idx = model.index(row, col)
                option = self.viewOptions()
                option.rect = self.visualRect(idx)

                if newPage:
                    offsetY = option.rect.y()
                    newPage = False

                option.rect.moveTop(option.rect.y()-offsetY)
                self.itemDelegate().paint(painter, option, idx)

        painter.end()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接