Question

Question

How can I create a QListWidget that has a minimum height but stretches to fill all available space even if the layout already has a stretch component?

Background

I'm using PySide to create dynamic User Interfaces. The components of the interface change depending on the context. My goal is to have a vertical layout as such:

Controls (grid layout with labels)
Stretch
Buttons (Main operation buttons)
StatusBar

The buttons and status bar are just QHBoxLayouts. I'm using a QDialog instead of a QMainWindow since this is often used from within another application such as Maya or Nuke. The dialog is built on the fly and sometimes a QListWidget can be added after the dialog is displayed. I can't predict when to addStretch and when not to.

Trials

I've tried using some of these bits of code to no avail:

# Set the size Policy.
listWidget.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding)

# Set a minimum Height
count = min(listBox.count(),12)
bestHeight = count*listBox.sizeHintForRow(0)+5
listBox.setMinimumHeight(bestHeight)

setMinimumHeight() as well as setSizeHint(), I've even tried subclassing the QListWidget to control the sizeHint function. * How to set minimum height of QListWidgetItem? * QListWidget adjust size to content

Example

This is a full example. The QListWidget is not stretching to fill the height. If I remove the addStretch() line, the QListWidget performs as I'd like, but I really want this to be dynamic.

#!/usr/bin/env python
import sys
from PySide import QtCore, QtGui

class myDialog(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QDialog.__init__(self, parent)
        self.setWindowTitle("Testing 123")

        # Declare Layouts.
        self.mainLayout=QtGui.QVBoxLayout()
        self.gridLayout=QtGui.QGridLayout()
        self.buttons = QtGui.QHBoxLayout()
        self.statusBarLayout = QtGui.QHBoxLayout()

        # Set margins.
        self.mainLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setContentsMargins(4, 4, 4, 4)
        self.buttons.setContentsMargins(0, 0, 0, 0)
        self.statusBarLayout.setContentsMargins(0, 0, 0, 0)

        # Assemble Layouts.
        self.mainLayout.addLayout(self.gridLayout)
        self.mainLayout.addStretch()
        self.mainLayout.addLayout(self.buttons)
        self.mainLayout.addLayout(self.statusBarLayout)

        self.setLayout(self.mainLayout)

        # Fill in Grid Layout.
        row = 0
        self.gridLayout.addWidget(QtGui.QLabel("ComboBox"), row, 0)
        combo = QtGui.QComboBox()
        combo.addItems(['A','B','C','1','2','3'])
        self.gridLayout.addWidget(combo, row, 1)
        row += 1

        self.gridLayout.addWidget(QtGui.QLabel("List"), row, 0)
        listWidget = QtGui.QListWidget()
        listWidget.addItems(['A','B','C','1','2','3'])
        self.gridLayout.addWidget(listWidget, row, 1)
        row += 1

        self.gridLayout.addWidget(QtGui.QLabel("LineEdit"), row, 0)
        self.gridLayout.addWidget(QtGui.QLineEdit(), row, 1)
        row += 1

        # Add some buttons.
        for x in ['One','Two']:
            self.buttons.addWidget(QtGui.QPushButton(x))

        # Add the psuedo status bar.
        self.statusBar = QtGui.QStatusBar()
        self.statusBarLayout.addWidget(self.statusBar, 4 )

        self.statusBar.showMessage("Hello World")

if __name__ == '__main__':
    app = QtGui.QApplication(sys.argv)
    dialog = myDialog()
    sys.exit(dialog.exec_())
Was it helpful?

Solution

I've figured it out. I need to increase the stretch factor of the gridLayout when I add it to the mainLayout. It has nothing to do with the QListWidget.

Here's the short of it:

self.mainLayout.addLayout(self.gridLayout, 1) # stretch factor > 0
self.mainLayout.addStretch(0) # Default is 0

OTHER TIPS

If you know the index of the spacer use the takeAt ( int index ) method to remove it, or else use a QSpacerItem instead, something like:

self.spacerItem = QtGui.QSpacerItem(
    20, 40,
    QtGui.QSizePolicy.Minimum,
    QtGui.QSizePolicy.Expanding
)
self.layout.addItem(self.spacerItem)

Then remove it with removeItem ( QLayoutItem * item ):

self.layout.removeItem(self.spacerItem)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top