【问题标题】:How to force QAbstractItemView recalculate items sizeHints如何强制 QAbstractItemView 重新计算项目 sizeHints
【发布时间】:2023-03-27 19:44:02
【问题描述】:

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

在谷歌中我发现可以从模型中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();
}

Similar question

【问题讨论】:

    标签: qt qlistview qsplitter


    【解决方案1】:

    在Qt源代码挖掘之后,我发现scheduleDelayedItemsLayout()函数正在解决我这边的问题。

    【讨论】:

      【解决方案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);
      

      它强制调整列表视图的大小,而列表视图本身会刷新其行大小。

      【讨论】:

        【解决方案3】:

        这有点猜测,但是设置 QListView 的调整大小模式有帮助吗?

        listView->setResizeMode( QListView::Adjust );
        

        【讨论】:

        • 没有帮助。目前,我连接到 QSplitter 的 splitterMoved 信号,并在每次调整时调用 view->model()->reset() 。我觉得不是很好,我现在会尝试测试它的很多项目。
        • view->model()->reset() 非常慢:(
        • @Cris,没办法。它受到保护。我需要所有视图都具有相同的行为,而不仅仅是 QListView。从文档 - “更新视图的子小部件的几何形状” - 我没有子小部件。
        • 我在使用 QTreeView 时遇到了类似的问题,reset 导致扩展状态也被重置,即一切都崩溃了。 updateGeometries 出于某种原因没有任何效果,即使我在调用它之前手动获取并打印了 Qt::SizeHintRole。调用scheduleDelayedItemsLayout 确实有效!
        【解决方案4】:

        其他解决方案都不适合我,但这确实有效:

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

        【讨论】:

        • 如何恢复滚动条位置?
        • 就我而言,我做到了:list-&gt;scrollTo(list-&gt;currentIndex(),QAbstractItemView::PositionAtCenter);。但如果您愿意,您可以跳转到任何其他索引。
        • 你是什么时候做的?在拆分事件上?您只需重置模型即可获得相同的效果,但速度要快 2 倍。
        • 我有一个按钮,每次按下按钮时都会更改项目的大小。不过,您对性能问题是正确的。但我一直在寻找比公开重置模型功能和恢复选择的代码更简单的东西。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-12-10
        • 2014-04-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        相关资源
        最近更新 更多