Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Set optimal size of a dialog window containing a TableWidget

Tags:

pyqt

pyqt4

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.

like image 355
rocksportrocker Avatar asked Aug 25 '11 11:08

rocksportrocker


2 Answers

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())
like image 173
Stephen Terry Avatar answered Oct 19 '22 11:10

Stephen Terry


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.

like image 22
alexisdm Avatar answered Oct 19 '22 10:10

alexisdm