PyQt5 listWidget refuse to get smaller in QtDesigner

Viewed 44

I have a layout in designer that looks like this:

enter image description here

except that I want the listWidget to be as small as possible, and only expand vertically based on the minimum height needed to hold all it's items. However for some reason it refuses to cooperate, and just remains at it's default size. I tried to do multiple things to change it:

  1. setting the stretch factor of textLabel to listWidget to be 1,0
  2. setting the sizePolicy of the listWidget as well as the widget it is in to be minimum
  3. setting the resizeMode of the listWidget to be adjust
  4. setting the sizePolicy of the button (I want it to fill up all the remaining space) to expanding
  5. setting the stretch factor of the widget to the button to 0,1

but none of these work. In addition, the window does not seem to be able to become smaller than this despite there being no minimum size set for anything, leading me to believe that there is an invisible minimum size for the listWidget that is not related to the minimum size shown in the properties. Anyone knows how to fix this?

Edit: after taking a suggestion of using preferred size policy and an expanding button, it still does not want to work. Here's the ui file for reference:

<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>Form</class>
 <widget class="QWidget" name="Form">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>318</width>
    <height>277</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Form</string>
  </property>
  <layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0">
   <property name="spacing">
    <number>0</number>
   </property>
   <property name="leftMargin">
    <number>0</number>
   </property>
   <property name="topMargin">
    <number>0</number>
   </property>
   <property name="rightMargin">
    <number>0</number>
   </property>
   <property name="bottomMargin">
    <number>0</number>
   </property>
   <item>
    <widget class="QWidget" name="widget" native="true">
     <property name="sizePolicy">
      <sizepolicy hsizetype="Minimum" vsizetype="Maximum">
       <horstretch>0</horstretch>
       <verstretch>0</verstretch>
      </sizepolicy>
     </property>
     <property name="baseSize">
      <size>
       <width>0</width>
       <height>0</height>
      </size>
     </property>
     <layout class="QVBoxLayout" name="verticalLayout" stretch="0,0">
      <property name="spacing">
       <number>0</number>
      </property>
      <property name="sizeConstraint">
       <enum>QLayout::SetDefaultConstraint</enum>
      </property>
      <property name="leftMargin">
       <number>0</number>
      </property>
      <property name="topMargin">
       <number>0</number>
      </property>
      <property name="rightMargin">
       <number>0</number>
      </property>
      <property name="bottomMargin">
       <number>0</number>
      </property>
      <item>
       <widget class="QLabel" name="label">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="text">
         <string>TextLabel</string>
        </property>
       </widget>
      </item>
      <item>
       <widget class="QListWidget" name="listWidget">
        <property name="sizePolicy">
         <sizepolicy hsizetype="Preferred" vsizetype="Maximum">
          <horstretch>0</horstretch>
          <verstretch>0</verstretch>
         </sizepolicy>
        </property>
        <property name="sizeAdjustPolicy">
         <enum>QAbstractScrollArea::AdjustToContents</enum>
        </property>
        <property name="resizeMode">
         <enum>QListView::Fixed</enum>
        </property>
       </widget>
      </item>
     </layout>
    </widget>
   </item>
   <item>
    <widget class="QPushButton" name="pushButton">
     <property name="sizePolicy">
      <sizepolicy hsizetype="Expanding" vsizetype="Minimum">
       <horstretch>0</horstretch>
       <verstretch>0</verstretch>
      </sizepolicy>
     </property>
     <property name="text">
      <string>PushButton</string>
     </property>
    </widget>
   </item>
  </layout>
 </widget>
 <resources/>
 <connections/>
</ui>
1 Answers

Set the stretch factors to default and then

  1. set QListWidget set vertical size policy to Preferred
  2. set the QPushButton vertical size policy to Expanding
  3. set the QLabel vertical size policy to Maximum
  4. Set the sizeAdjuctPolicy for QListWidget to AdjustToContents

The size policies in qt are not what they seem upon first glance. Minimum actually means grow as much as you can. Maximum actually means shrink as much as you can. you can learn more about them in the Qt docs

The last part you can do is overwrite the QListWidget.sizeHint method to dynamically adjust to the number of items in the list.

Here is a runnable example:

from PySide6.QtCore import *
from PySide6.QtWidgets import *

class ListWidget(QListWidget):

    def sizeHint(self):
        size = super().sizeHint()
        frame = self.frameWidth() * 2
        items_height = self.count() * self.sizeHintForRow(0)
        height = min(super().maximumHeight(), items_height)
        size.setHeight(height + frame)
        return size

    def minimumSizeHint(self):
        return self.sizeHint()

class MainWindow(QMainWindow):

    def __init__(self, parent=None):
        super().__init__(parent=parent)
        self.resize(318, 277)
        self.centralwidget = QWidget(self)
        self.verticalLayout = QVBoxLayout(self.centralwidget)
        sizePolicy = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
        sizePolicy1 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Expanding)
        sizePolicy2 = QSizePolicy(QSizePolicy.Minimum, QSizePolicy.Maximum)
        self.setCentralWidget(self.centralwidget)
        self.label = QLabel('Label', self.centralwidget)
        self.listWidget = ListWidget(self.centralwidget)
        self.pushButton = QPushButton('Push Button', self.centralwidget)
        self.label.setSizePolicy(sizePolicy2)
        self.listWidget.setSizePolicy(sizePolicy)
        self.listWidget.setSizeAdjustPolicy(QAbstractScrollArea.AdjustToContents)
        self.pushButton.setSizePolicy(sizePolicy1)
        self.verticalLayout.addWidget(self.label)
        self.verticalLayout.addWidget(self.listWidget)
        self.verticalLayout.addWidget(self.pushButton)
        self.pushButton.clicked.connect(self.additem)

    def additem(self):
        i = self.listWidget.count()
        self.listWidget.addItem(QListWidgetItem("Item" + str(i), type=0))


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    window.show()
    app.exec()
Related