1

I have a QListWidget which contains QListWidgetItems that exceed its visible boundaries and I would like to add a vertical Scrollbar. I have tried the following:

sz = QtCore.QSize(200,200)
_lstwdgt = QtGui.QListWidget(parent)
_item = QtGui.QListWidgetItem(_lstwdgt)
_widget = QtGui.QWidget(parent)
_layout = QtGui.QVBoxLayout()
for n in range(0,10):
    _btn = QtGui.QPushButton("test {}".format(n), parent)
    _layout.addWidget(_btn)
_layout.addStretch()
_layout.setSizeConstraint(QtGui.QLayout.SetFixedSize)
_widget.setLayout(_layout)
_item.setSizeHint(_widget.sizeHint())
_lstwdgt.addItem(_item)
_lstwdgt.setItemWidget(_item,_widget)
_lstwdgt.setFixedSize(sz)
vScrollBar = QtGui.QScrollBar(_lstwdgt)
_lstwdgt.setVerticalScrollBar(vScrollBar)

but no vertical scrollbar becomes visible. When I change _layout to be QHBoxLayout() however, a horizontal scrollbar will appear, what is missing to get a vertical scrollbar instead?

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
stdcerr
  • 13,725
  • 25
  • 71
  • 128
  • It is not necessary to add scrollbar as QListWidget already has them, please provide a [mre] – eyllanesc Apr 08 '21 at 16:36
  • ...and make them more readable. _Naming _everything _like _this _is _not _very _good _for _reading _code _and _it _doesn't _provide _any _benefit. – musicamante Apr 08 '21 at 16:56

1 Answers1

1

The problem is that by default every view uses the ScrollPerItem scroll mode: with this mode, the scroll bar is only used to scroll between items, and since your view only has one item, Qt doesn't think it has to show the scroll bar.

The solution is to change the mode to ScrollPerPixel:

_lstwdgt.setVerticalScrollMode(QtGui.QListWidget.ScrollPerPixel)

Note that if you only need to add widgets to a scrollable area, using a QListWidget is really a very bad idea, and a QScrollArea should be used instead.
Also, adding a stretch is completely pointless since you're using the sizeHint for the item, and size hints only returns the minimal optimal size (which ignores any stretch, which are spacers that can be shrunk to 0 sizes).

I also strongly suggest you to use more verbose variable names, there's really no benefit in abbreviating names like _lstwdgt (nor adding underscore prefixes for every object in a local scope); it took me more time to understand what your code did than to actually find the reason of your problem. Remember, readability is really important in programming.

musicamante
  • 41,230
  • 6
  • 33
  • 58
  • Thanks a lot for this and also for the additional suggestion as to improve readability! As for `QListWidget` vs `QScrollArea`, why would the latter be preferred? – stdcerr Apr 08 '21 at 17:43
  • 1
    @stdcerr QListWidget is used to show items of a *data model*, like a list of names, numbers, similarly to what QTableWidget does, but just with a single column; note that both of them, along with QTreeWidget, are higher level widgets that subclass their base view widget (QListView, QTableView and QTreeView respectively), by implementing an internal data model. While in some cases they *can* be used as widget containers, that's not their scope. Also, all of them actually inherit from QAbstractScrollArea, like QScrollArea does, which is the widget you should primarily consider for scroll areas. – musicamante Apr 08 '21 at 17:54
  • 1
    I strongly suggest you to read and understand the [description about QListWidget](https://doc.qt.io/qt-5/qlistwidget.html#details) (and deepen by reading all docs related to classes and topics referenced there), then take your time to read the [Qt Model/View programming](https://doc.qt.io/qt-5/model-view-programming.html) chapter. You'll clearly see that those classes have absolutely *nothing* to do with laying out widgets in a scroll area. Again, while in *some* situations they *can* be used like that, that is more a *possible* usage (almost some sort of "hack") than an actual purpose. – musicamante Apr 08 '21 at 17:58