Search code examples
pythonpyqtpyqt5qlistwidget

QListWidget display more items


Here is a picture of my GUI:

enter image description here

I want to display all 100 items in my list widget without an inner scroll bar (there is an outer scroll bar, so there is no issue that I cannot fit all the items).

I have tried disabling the scroll bar for the list widget, but that didn't increase the number of items the list widget was displaying.

Here is my code:

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys

if __name__ == "__main__":
    app = QApplication(sys.argv)

    dlg = QDialog()

    listWidget = QListWidget()
    for i in range(100):
        listWidget.addItem(QListWidgetItem("Item " + str(i)))

    layout1 = QVBoxLayout()
    layout1.addWidget(QLabel("Label 1"))
    groupBox1 = QGroupBox("Group 1")
    groupBox1.setLayout(layout1)

    layout2 = QVBoxLayout()
    layout2.addWidget(listWidget)
    groupBox2 = QGroupBox("Group 2")
    groupBox2.setLayout(layout2)

    nestedWidgetLayout = QVBoxLayout()
    nestedWidgetLayout.addWidget(groupBox1)
    nestedWidgetLayout.addWidget(groupBox2)
    nestedWidget = QWidget()
    nestedWidget.setLayout(nestedWidgetLayout)

    scrollArea = QScrollArea()
    scrollArea.setWidget(nestedWidget)

    mainLayout = QVBoxLayout()
    mainLayout.addWidget(scrollArea)
    dlg.setLayout(mainLayout)

    dlg.show()

    app.exec()

Solution

  • The @a_manthey_67 solution gives us a starting point but has several limitations:

    • It is calculated for a specific number of items so if items are added/deleted it will fail.
    • Manually set the height of each item instead of obtaining the height set by the style.

    Considering the above, I have implemented a similar logic using sizeHintForRow(), in addition to enabling the widgetResizable property of the QScrollArea and disabling the verticalScrollBar.

    import sys
    
    from PyQt5.QtCore import pyqtSlot, Qt
    from PyQt5.QtWidgets import (
        QApplication,
        QDialog,
        QGroupBox,
        QLabel,
        QListWidget,
        QListWidgetItem,
        QScrollArea,
        QVBoxLayout,
        QWidget,
    )
    
    
    class ListWidget(QListWidget):
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
            self.model().rowsInserted.connect(self._recalcultate_height)
            self.model().rowsRemoved.connect(self._recalcultate_height)
    
        @pyqtSlot()
        def _recalcultate_height(self):
            h = sum([self.sizeHintForRow(i) for i in range(self.count())])
            self.setFixedHeight(h)
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
    
        dlg = QDialog()
    
        listWidget = ListWidget()
        for i in range(100):
            listWidget.addItem(QListWidgetItem("Item " + str(i)))
    
        layout1 = QVBoxLayout()
        layout1.addWidget(QLabel("Label 1"))
        groupBox1 = QGroupBox("Group 1")
        groupBox1.setLayout(layout1)
    
        layout2 = QVBoxLayout()
        layout2.addWidget(listWidget)
        groupBox2 = QGroupBox("Group 2")
        groupBox2.setLayout(layout2)
    
        nestedWidget = QWidget()
        nestedWidgetLayout = QVBoxLayout(nestedWidget)
        nestedWidgetLayout.addWidget(groupBox1)
        nestedWidgetLayout.addWidget(groupBox2)
    
        scrollArea = QScrollArea(widgetResizable=True)
        scrollArea.setWidget(nestedWidget)
    
        mainLayout = QVBoxLayout(dlg)
        mainLayout.addWidget(scrollArea)
    
        dlg.show()
    
        sys.exit(app.exec_())