9

I have QListView and QTabWidget inside QSplitter. QListView is using custom model and custom delegates. In delegate I reimplemented paint and sizeHint methods. But when I resize view - height of elements doesn't recalculated. How can I fix it? Sample images:

Before resizingAfter resizing

In google I found that it is possible to emit layoutChanged from the model, but I want only current view to be updated, because content of model doesn't change.

Delegate code:

void ChatItemDelegate::paint( QPainter *painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    painter->save();

    ChatItem *item = static_cast< ChatItem * >( index.internalPointer() );
    QTextDocument doc;

    doc.setHtml( item->htmlText() );
    doc.setTextWidth( option.rect.width() );

    QRect clip( 0, 0, option.rect.width(), option.rect.height() );
    painter->translate( option.rect.topLeft() );

    QColor bgColor = index.row() % 2 ? QColor( 255, 0, 0, 40 ) : QColor( 0, 255, 0, 40 );
    painter->fillRect( clip, bgColor );
    doc.drawContents( painter, clip );

    qDebug() << "paint: " << option.rect.width() << " idx: " << index.row();

    painter->restore();
}

QSize ChatItemDelegate::sizeHint( const QStyleOptionViewItem& option, const QModelIndex& index ) const
{
    ChatItem *item = static_cast< ChatItem * >( index.internalPointer() );
    QTextDocument doc;

    doc.setHtml( item->htmlText() );
    doc.setTextWidth( option.rect.width() );

    qDebug() << "hint:  " << option.rect.width() << " idx: " << index.row();

    return doc.size().toSize();
}

Similar question

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Dmitry Sazonov
  • 8,801
  • 1
  • 35
  • 61

5 Answers5

5

After digging in Qt source code, I found that scheduleDelayedItemsLayout() function is solving the issue on my side.

lp35
  • 198
  • 3
  • 9
  • 1
    Thank you, I've been racking my brain for a while trying to sort this issue. I added this in my view's resizeEvent and my delegates suddenly started resizing themselves properly. – Erwan Leroy Apr 05 '22 at 05:36
2

Experiencing the same issue in November 2017...

The only way I found to resolve it is this ugly hack :

   QSize size = listView->viewport()->size();
   size.setHeight(size.height()+1);
   listView->viewport()->resize(size);

   size.setHeight(size.height()-1);
   listView->viewport()->resize(size);

It forces a resize on the listview, which itself refreshes its row sizes.

Mickaël C. Guimarães
  • 1,020
  • 2
  • 14
  • 32
1

This is a bit of a guess, but does setting your QListView's resize mode help?

listView->setResizeMode( QListView::Adjust );
Chris
  • 17,119
  • 5
  • 57
  • 60
  • Doesn't helped. Currently I connected to splitterMoved signal of QSplitter and call view->model()->reset() on each sizing. I don't think that it's good, i'll try to test it for a lot of items now. – Dmitry Sazonov May 08 '13 at 15:52
  • view->model()->reset() is mega-slow :( – Dmitry Sazonov May 08 '13 at 15:59
  • @Cris, no way. It's protected. I need same behavior for all views, not only for QListView. From documentation - "Updates the geometry of the child widgets of the view" - I don't have child widgets. – Dmitry Sazonov May 09 '13 at 08:22
  • I have a similar problem when using QTreeView and `reset` leads to the expansion states also getting reset, i.e., everything gets collapsed. `updateGeometries` has no effect for some reason even though I manually get and print the `Qt::SizeHintRole` before calling it. Calling `scheduleDelayedItemsLayout` does indeed work! – mxmlnkn Aug 09 '19 at 15:28
0

None of the other solutions worked for me but this did:

listView->setViewMode(QListView::IconMode);
listView->setViewMode(QListView::ListMode);
Arnaud
  • 3,765
  • 3
  • 39
  • 69
  • How to you recover a scroll bar position? – Dmitry Sazonov Dec 21 '21 at 16:10
  • In my case I did: `list->scrollTo(list->currentIndex(),QAbstractItemView::PositionAtCenter);`. But you can jump to any other index if you wish. – Arnaud Dec 21 '21 at 19:40
  • And when you did it? On a splitter event? You can just reset a model to get the same effect, but with x2 speed. – Dmitry Sazonov Dec 28 '21 at 12:46
  • I have a button which changes the size of the items each time the button is pressed. You are correct about the performance issue though. But I was looking for something a little simpler than making reset model functions public and having code for restoring selection. – Arnaud Dec 28 '21 at 15:09
0

What about QAbstractItemView::doItemsLayout()

https://code.woboq.org/qt5/qtbase/src/widgets/itemviews/qabstractitemview.cpp.html#_ZN17QAbstractItemView13doItemsLayoutEv

I have no idea, why this function exists on Qt Sources as a public API, but have not been documented, but seems, it's works fine for me