43

Is it possible to adjust QListWidget height and width to it's content?

sizeHint() always returns 256, 192 no matter what its content is.
QListWidgetItem's sizeHint() returns -1, -1, so I can not get content width.

Problem the same as here - http://www.qtcentre.org/threads/31787-QListWidget-width , but there is no solution.

enter image description here

import sys
from PyQt4.QtGui import *

class MainWindow(QWidget):
    def __init__(self, parent=None):
        QWidget.__init__(self, parent)

        list = QListWidget()
        list.addItem('111111111111111')

        vbox = QVBoxLayout(self)
        vbox.addWidget(list)

app = QApplication(sys.argv)
myapp = MainWindow()
myapp.show()
sys.exit(app.exec_())
Blackbelt
  • 156,034
  • 29
  • 297
  • 305
Qiao
  • 16,565
  • 29
  • 90
  • 117

6 Answers6

62

sizeHint() always returns 256, 192 no matter what its content is.

Thats because this is the size of the QListWidget, the viewport, not the items. sizeHintForColumn() will give you the max size over all items, so you can resize the widget like this:

list.setMinimumWidth(list.sizeHintForColumn(0))

If you don't want to force minimum width, then subclass and provide this as the size hint instead. E.g.:

class ListWidget(QListWidget):
  def sizeHint(self):
    s = QSize()
    s.setHeight(super(ListWidget,self).sizeHint().height())
    s.setWidth(self.sizeHintForColumn(0))
    return s
tomvodi
  • 5,577
  • 2
  • 27
  • 38
gwohpq9
  • 2,143
  • 2
  • 18
  • 18
  • It works. Just need adding +5 px so there no scrollbar. Where can I read about viewports? Can not find it. – Qiao Jun 16 '11 at 16:40
  • 2
    Check out QAbstractScrollArea – gwohpq9 Jun 16 '11 at 16:55
  • 1
    If there will be a vertical srollbar, use the following two lines, after inserting ListWidget in desired layout: `list_widget.updateGeometry()` and then add `list_widget.verticalScrollBar().width()` – Jeff Mar 03 '14 at 15:38
  • Doesn't work with Qt 5.2. `sizeHintForColumn(0)` returns the same number as `sizeHint().width()`, and it way more than neccessary. – Violet Giraffe May 02 '14 at 18:24
  • Not working for me in qt 5.8, I using this code instead, and it worked perfectly:/* make the selection NOT span the entire width of the view */ QListView { show-decoration-selected: 0; } // and for selected: if(index.row() < 0 || index.data().toString().length()*7 < pos.x()){ qDebug() << "We will show default a context menu"; QAction *createFolderAct = menu.addAction(tr("New Folder")); } – nobjta_9x_tq Dec 27 '16 at 03:53
  • See here for stylesheet: http://doc.qt.io/qt-5/stylesheet-examples.html#customizing-qlistview – nobjta_9x_tq Dec 27 '16 at 04:04
17

Using takois answer I played around with the sizeHintForColumn or sizeHintForRow and found that you have to add slightly larger numbers, because there might be some style dependent margins still. ekhumoros comment then put me on the right track.

In short the full size of the list widget is:

list.sizeHintForColumn(0) + 2 * list.frameWidth()
list.sizeHintForRow(0) * list.count() + 2 * list.frameWidth())

According to the comment by Violet it may not work in Qt 5.

Also be aware that setting the size to the content, you don't need scrollbars, so I turn them off.

My full example for a QListWidget ajusted to its content size:

from PySide import QtGui, QtCore

app = QtGui.QApplication([])

window = QtGui.QWidget()
layout = QtGui.QVBoxLayout(window)
list = QtGui.QListWidget()
list.addItems(['Winnie Puh', 'Monday', 'Tuesday', 'Minnesota', 'Dracula Calista Flockhart Meningitis', 'Once', '123345', 'Fin'])
list.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
list.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
list.setFixedSize(list.sizeHintForColumn(0) + 2 * list.frameWidth(), list.sizeHintForRow(0) * list.count() + 2 * list.frameWidth())
layout.addWidget(list)

window.show()

app.exec_()
Community
  • 1
  • 1
NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
2

In order to effectively use sizeHint, you have to override it, at least in c++. In my experience, the default implementations for widgets can be pretty useless when you want a specific behavior. Attempts to force what you want with spacers or layouts end in disaster. If you can derive from QListWidget and override sizeHint, you can iterate through your items and find the longest string, then do some kind of magic to determine how wide it should be.

That's what I'd do, anyway.

Thadeux
  • 146
  • 1
  • 8
0

First you should get your largest string in the list, that is easy to obtain.

After you get that string, do the following:

QFontMetrics * fm = new QFontMetrics(widget->font());
QRect rect;
rect = fm->boundingRect(string);

rect.width() has the width in pixels of the largest string rect.height() has it's height.

Set the QListWidget width to that rect's width (plus the margins) and it's height to that rect's height times the number of items

I didn't test the code, but hope it puts you on the right track

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43
-1
QListWidget *valList;

valList =  new QListWidget(this);

valList->setSizePolicy (QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored));
valList->setMinimumSize (QSize(1111, 111));
NorthCat
  • 9,643
  • 16
  • 47
  • 50
barcaleiku
  • 39
  • 1
-3

You need to get the QHeaderView of your QListWidget and adjust its resize mode.

Read this documentation for more information

http://doc.qt.nokia.com/latest/qheaderview.html#ResizeMode-enum

Raj
  • 22,346
  • 14
  • 99
  • 142
  • And where can I read about getting the QHeaderView of your QListWidget? Can not find mentioning about header in docs of list and its parents classes. – Qiao Jun 15 '11 at 00:28
  • okay forget about the QHeaderView. After setting the size policy, try setting the resize mode to Adjust [doc](http://doc.qt.nokia.com/latest/qlistview.html#ResizeMode-enum) – Raj Jun 15 '11 at 02:54
  • It does not work. `sizeHint()` always returns 256, 192, size policy can not change it. – Qiao Jun 15 '11 at 23:16