rocksportrocker
rocksportrocker

Reputation: 7419

Set optimal size of a dialog window containing a TableWidget

I wrote a little dialog which only contains a TableWigdet. How can I determine the horizontal size of the table ? I want to resize the dialog window so that the table is displayed without a horizontal scrollbar.

Upvotes: 6

Views: 7114

Answers (2)

alexisdm
alexisdm

Reputation: 29886

You could use something like that (commented enough I hope):

from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyTableWidget(QTableWidget):  
    def __init__(self, x, y, parent = None):
        super(MyTableWidget, self).__init__(x, y, parent)

        self.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOn)

        # To force the width to use sizeHint().width()
        self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Preferred)

        # To readjust the size automatically...
        # ... when columns are added or resized
        self.horizontalHeader().geometriesChanged \
             .connect(self.updateGeometryAsync)
        self.horizontalHeader().sectionResized \
             .connect(self.updateGeometryAsync)        
        # ... when a row header label changes and makes the
        # width of the vertical header change too
        self.model().headerDataChanged.connect(self.updateGeometryAsync)

    def updateGeometryAsync(self):      
        QTimer.singleShot(0, self.updateGeometry)

    def sizeHint(self):
        height = QTableWidget.sizeHint(self).height()

        # length() includes the width of all its sections
        width = self.horizontalHeader().length() 

        # you add the actual size of the vertical header and scrollbar
        # (not the sizeHint which would only be the preferred size)                  
        width += self.verticalHeader().width()        
        width += self.verticalScrollBar().width()       

        # and the margins which include the frameWidth and the extra 
        # margins that would be set via a stylesheet or something else
        margins = self.contentsMargins()
        width += margins.left() + margins.right()

        return QSize(width, height)

When a row header changes, the width of the whole vertical header changes, but not right away after the signal headerDataChanged is emitted.
That's why I used a QTimer to call the updateGeometry (which must be called when sizeHint changes) after QTableWidget has actually updated the vertical header width.

Upvotes: 6

Stephen Terry
Stephen Terry

Reputation: 6279

As far as I know, there's no easy way to do it. You have to sum over the widths of the table's columns and then add space for the headers. You also have to add space for the vertical scrollbar and the widget frame. Here is one way to do it,

class myTableWidget(QtGui.QTableWidget):

    def sizeHint(self):
        width = 0
        for i in range(self.columnCount()):
            width += self.columnWidth(i)

        width += self.verticalHeader().sizeHint().width()

        width += self.verticalScrollBar().sizeHint().width()
        width += self.frameWidth()*2

        return QtCore.QSize(width,self.height())

Upvotes: 6

Related Questions