如何强制QAbstractItemView重新计算项目的sizeHints

9

我有一个QSplitter,里面包含了QListView和QTabWidget。QListView使用自定义模型和自定义委托。在委托中,我重新实现了paint和sizeHint方法。但是当我调整视图大小时,元素的高度不会重新计算。我该如何解决这个问题?示例图片:

Before resizingAfter resizing

在Google上我发现有可能从模型中emit layoutChanged,但我只想更新当前视图,因为模型的内容并没有改变。
委托代码:
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();
}

类似的问题

5个回答

5

1
谢谢,我已经绞尽脑汁一段时间试图解决这个问题。我在我的视图的resizeEvent中添加了这个,我的代理突然开始正确地调整大小了。 - Erwan Leroy

2

2017年11月我也遇到了同样的问题...

我发现唯一解决办法是这种丑陋的方法:

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

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

它会强制列表视图重新调整大小,从而刷新其行大小。

1
这只是一个猜测,但设置您的QListView的调整大小模式是否有帮助?
listView->setResizeMode( QListView::Adjust );

没有帮助。目前我连接到QSplitter的splitterMoved信号,在每次调整大小时调用view->model()->reset()。我觉得这不太好,现在我将尝试为许多项进行测试。 - Dmitry Sazonov
view->model()->reset() 的执行速度非常慢 :( - Dmitry Sazonov
@Cris,不行。它是受保护的。我需要所有视图都具有相同的行为,而不仅仅是QListView。根据文档,“更新视图的子窗口小部件的几何形状”- 我没有子窗口小部件。 - Dmitry Sazonov
当我使用QTreeView时,我遇到了类似的问题,即reset会导致展开状态也被重置,即所有内容都被折叠。尽管在调用updateGeometries之前手动获取并打印了Qt::SizeHintRole,但它似乎没有任何效果。调用scheduleDelayedItemsLayout确实有效! - mxmlnkn

0

其他的解决方案对我都不起作用,但这个可以:

listView->setViewMode(QListView::IconMode);
listView->setViewMode(QListView::ListMode);

如何恢复滚动条位置? - Dmitry Sazonov
在我的情况下,我执行了以下操作:list->scrollTo(list->currentIndex(),QAbstractItemView::PositionAtCenter);。但是如果您愿意,也可以跳转到任何其他索引。 - Arnaud
你是在什么时候做的?在分裂事件上吗?你可以重置模型以获得相同的效果,但速度提高了两倍。 - Dmitry Sazonov
我有一个按钮,每次按下它都会改变项目的大小。你关于性能问题是正确的。但是我正在寻找比公开重置模型函数并编写恢复选择代码更简单的东西。 - Arnaud

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接