我有一个QListView,里面有很多不同高度的东西。我为绘画项实现了一个自定义委托,并将布局模式设置为批处理。
但是,在分配模型时,list视图会预先请求模型中的每个项的sizeHint,忽略批处理设置,从而破坏性能,因为要计算大小,委托必须布局大量文本(这不是快速的)。
可能这样做是为了计算滚动条位置,但我估计,当项目数量很大时,滚动条位置只能基于项索引,而不考虑项目高度。然而,这似乎不是QListView的工作方式。
我还尝试在模型中使用canFetchMore/fetchMore,但这会导致用户体验不良--滚动条的位置不再准确,而且当加载更多的项目时,列表会跳来跳去,它一点也不流畅。
因此,问题是:
非常感谢!
UPD:是再现此行为的最小示例:https://github.com/ajenter/qt_hugelistview
注意,启动延迟很大,调试消息显示所有5000项的sizeHint都是预先请求的。
发布于 2020-11-23 13:05:40
好吧,看来我找到了一个解决方案,所以为了任何有同样问题的人,我会在这里分享它,并搜索这个线程。
首先,我发现这实际上是2011年注册的Qt中的一个bug,至今仍处于打开状态:https://bugreports.qt.io/browse/QTBUG-16592
我已经投了我的一票(你也应该这么做!)然后决定尝试使用QTableView而不是QListView --而且,很显然,我设法让它工作了,或者看起来是这样的。
与QListView不同,QTableView只在显式请求时通过调用resizeRowToContents(rowNum)来调整行的大小。所以诀窍是,对于那些在视图中可见的行,以一种及时的方式调用它。
我所做的是:
。
MyTableView::MyTableView(QWidget* parent) : QTableView(parent)
{
setSelectionBehavior(QAbstractItemView::SelectRows);
horizontalHeader()->setStretchLastSection(true);
horizontalHeader()->hide();
verticalHeader()->hide();
setItemDelegateForColumn(0, new CustomDelegate(&table)); // for custom-drawn items
}。
QItemSelection _itemsWithKnownHeight; // private member of MyTableView
void MyTableView::updateVisibleRowHeights()
{
const QRect viewportRect = table.viewport()->rect();
QModelIndex topRowIndex = table.indexAt(QPoint(viewportRect.x() + 5, viewportRect.y() + 5));
QModelIndex bottomRowIndex = table.indexAt(QPoint(viewportRect.x() + 5, viewportRect.y() + viewportRect.height() - 5));
qDebug() << "top row: " << topRowIndex.row() << ", bottom row: " << bottomRowIndex.row();
for (auto i = topRowIndex.row() ; i < bottomRowIndex.row() + 1; ++i)
{
auto index = model()->index(i, 0);
if (!_itemsWithKnownHeights.contains(index))
{
resizeRowToContents(i);
_itemsWithKnownHeights.select(index, index);
qDebug() << "Marked row #" << i << " as resized";
}
}
}resizeEvent()、清除_itemsWithKnownHeights并再次调用updateVisibleRowsHeight() . table.setModel(&myModel);
table.updateVisibleRowHeights();实际上,它应该在MyTableView的一些方法中完成,该方法可以对更改进行建模,但我将把它作为一个练习。
中添加以下内容
connect(verticalScrollBar(), &QScrollBar::valueChanged, [this](int) {
updateRowHeights();
});完成-它的工作非常快,即使与模型的10万件!而且启动是即时的!
这个技术的基本概念证明(使用纯QTableView而不是子类)可以在这里找到:https://github.com/ajenter/qt_hugelistview/blob/tableview-experiment/src/main.cpp。
警告:这种技术还没有被证明,而且可能包含一些未知的问题。自食其果!
https://stackoverflow.com/questions/64924570
复制相似问题