Search code examples
pythonpyqt5screenshotqtablewidget

save a QWidget as an image


In pyqt5 i try:

fileName = "qtable_widget.png"
pixmap = QtGui.QPixmap(self.parent_self.main_self.ui_scheduled_transmitions_create_window.review_table.size())
self.parent_self.main_self.ui_scheduled_transmitions_create_window.review_table.render(pixmap)
pixmap.save("qtable_widget.png", "PNG", -1)

But this captures only the view area of the QTableWidget. The QTableWidget has a vertical scrollbar. Is there any way to capture all the qtablewidget?


Solution

  • A scroll area is implemented in a way that only the visible contents are actually painted, and only when they are exposed within the viewport.

    This means that you cannot simply call painting functions (which is what render() does) as you will always get the visible rectangle of the widget.

    The solution is then to temporarily resize the table in order to expose all the contents.

    My suggestion is to use a temporary table view, and set the same model on the original one.

    The trick is to get the proper content area, which includes a rectangle starting from the viewport position and has a size based on the viewportSizeHint(). In order for this to work properly, the view should have both scroll bars disabled, so that you can get the proper size hint, then adjust the rectangle top left to the view origin point (0, 0), and add the right and bottom margins using the frameWidth().

    This is a simple example of the above:

    # just an example table
    original = QTableWidget(100, 100)
    for r in range(100):
        for c in range(100):
            original.setItem(r, c, QTableWidgetItem('{} {}'.format(r, c)))
    
    
    temp = QTableView()
    temp.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
    temp.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
    temp.setModel(original.model())
    
    rect = QRect(temp.viewport().pos(), temp.viewportSizeHint())
    rect.setTopLeft(QPoint())
    margins = temp.contentsMargins()
    temp.resize(rect.size() + QSize(margins.right(), margins.bottom()))
    
    image = temp.grab()
    image.save('qtable_widget.png')
    temp.deleteLater()