Important: Please read the Qt Code of Conduct -

QTListView with Item delegate - Taller item rows for selected items

  • I have a multiple-selection enabled QListView with an Item delegate (QStyledItemDelegate) I use for setting the size for items and doing custom paint. My requirements are extremely simple:

    • Row height 30 for non selected items
    • Row height 60 for selected items

    Couldn't get this to work. Tried using the sizeHint on my QStyledItemDelegate

    @if (option.state & QStyle::State_Selected)
    return QSize(100,60); /// <<<<------ NEVER REACHED
    return QSize(100,30);

    The state is never selected which is weird because the same if statement works perfectly for the painting method on the same class, distinguishing between selected rows and non-selected rows for different paint background.

    Then I tried something else

    I made the selection model (QItemSelectionModel) accessible to the sizeHint method on my delegate. Using this I can query successfully if the row the sizehint is called for is selected or not and I am returning the correct size. However now only the drawing is done in the correct variable size. for selected items, the drawing now has a height of 60, which is correct, but it overlaps the items underneath it. In other words: the new calculated size is used only for DRAWING, but not for actually making the QListView item taller. It seems there is a missing call to "update" the listView that one of its items has changed in size. I don't need just to draw the item taller, i need the item to BE taller for that purpose.

    It seems that the sizeHint only has influence on the item height at the beginning when everything is initialized. if you all of a sudden return a higher height value for one of the items from your sizeHint -- it won't augment the listview to accommodate the new height.

    One interesting observation which may hold the key to the solution:

    If I set setResizeMode(QListView::Adjust) on my QListView, a slight resize to the control will trigger a re-calc of all the items, fixing the size of the actual selected item such the drawing (which is always done in the correct height) doesn't cascade over the item beneath as the item height is now correct. This is what I need to do as selection changes, cause a "re-calc" like the QLiustView::Adjust causes. How do I do that?

    What I'm doing now is ugly, and I'm positive it's not way to do this, but I have no other alternative. I am hooking up to the selection model -- listening on selection changes, and when they come, i resize my QlistView's height by 1 and then go back to the original size. This generates a recalculation of the item sizes (setResizeMode(QListView::Adjust) and everything looks and works fine. I just get nauseous by having to do this-- is there no better way to cause the items to re-calc their height NOT by faking a resize of the QListView?

  • Perhaps you can make the resize fake slightly less ugly by sending a resize event to the listview?

    I think that for this kind of work, Quick is much better. Perhaps you can use a simple QML for your listview instead? There, it is quite easy to make a delegate adjust its height...

  • This is what I ended up doing Andre, the user won't notice it, but it's rather sad that true dynamic row height modifications require a phantom "nowhere to nowhere" resize for QListView controls. I thought i'd find better support for such a basic functionality from a tool as advanced as Qt.

    Unfortunately I can't move to QML right now- i've invested too much effort already on my custom drawn QListView. Thanks for your response.

Log in to reply