QML ListView如何估计其contentItem的高度/宽度 [英] How does the QML ListView estimates the height/width of it's contentItem
问题描述
我想知道ListView
如何估计其contentItem
的高度/宽度,尽管该委托人是您不能问到的Component
,并且大小可能因一个委托实例而异.
I am wondering how the ListView
estimates the height/width of it's contentItem
, though the delegate is a Component
that you can't ask, and the size might vary from one delegate-instance to another.
- 它不使用当前实例的平均大小.
否则,在示例1 中,如果按下一个元素,则如果计算所有实例,则估计大小将为 3055.5 ,如果仅计算其中的那些实例,则估计大小为 3125 视图被计算在内.估计 2845 - 它不使用所有当前实例的最大大小.
如果按下一个元素,则估计大小为 7500 .如果仅考虑非实例化元素的最大高度,则为 6350 - 它不使用所有当前实例的最小大小.
估计肯定会很小.
- It does not use the average size of the current instances.
Otherwise in Example 1, if one element is pressed, the estimated size would be 3055.5 if all instances are counted, or 3125 if only those in the view are counted. It estimates 2845 - It does not use the maximums size of all current instances.
If one element is pressed, the estimated size would be 7500. If the maximum height is only considered for non-instantiated elements, it would be 6350 - It does not use the minimum size of all current instances.
The estimation would be definitely to small.
即使您知道正确的大小,也无济于事,因为在示例1 中,我们知道正确的contentHeight
为 2500 (如果没有)按下,然后按 2650 .在示例2 中,右边的contentHeight
将为 1225 ,但是手动设置该值没有用,因为此值很快就会被覆盖.
And even if you know the right size, you can't help it, for in Example 1 we know the correct contentHeight
would be 2500 if nothing is pressed, and 2650 if something is pressed. In Example 2 the right contentHeight
would be 1225 but setting manually setting the value is of no use, as it is overwritten soon after.
示例1:
ListView {
id: lv1
width: 200
height: 500
model: 50
onContentHeightChanged: console.log('estimated contentHeight', contentHeight)
delegate: Rectangle {
width: 200
height: ma.pressed ? 150 : 50
border.color: 'black'
Text {
anchors.centerIn: parent
text: index
}
MouseArea {
id: ma
anchors.fill: parent
}
}
}
示例2:
ListView {
id: lv1
width: 200
height: 500
model: 50
onContentHeightChanged: console.log('estimated contentHeight', contentHeight)
delegate: Rectangle {
width: 200
height: index
border.color: 'black'
Text {
anchors.centerIn: parent
text: index + ' ' + ((index * (index + 1)) / 2)
}
}
}
推荐答案
我不知道.让我们看一下源代码. :)
I don't know. Let's look through the source code. :)
查看代码,这是设置contentWidth
和contentHeight
的:
Looking at the code, here's where the contentWidth
and contentHeight
are set:
void QQuickItemViewPrivate::updateViewport()
{
Q_Q(QQuickItemView);
qreal extra = headerSize() + footerSize();
qreal contentSize = isValid() || !visibleItems.isEmpty() ? (endPosition() - startPosition()) : 0.0;
if (layoutOrientation() == Qt::Vertical)
q->setContentHeight(contentSize + extra);
else
q->setContentWidth(contentSize + extra);
}
startPosition()
和endPosition()
函数声明为此处:
qreal QQuickItemViewPrivate::startPosition() const
{
return isContentFlowReversed() ? -lastPosition() : originPosition();
}
qreal QQuickItemViewPrivate::endPosition() const
{
return isContentFlowReversed() ? -originPosition() : lastPosition();
}
QQuickListView
的originPosition()
和lastPosition()
的实现都是 averageSize
似乎是该函数由 QQuickListViewPrivate::visibleItemsChanged()
,由
That function is called by QQuickListViewPrivate::visibleItemsChanged()
, which is called by QQuickItemViewPrivate::refill()
, which is called... all over the place. Basically whenever anything related to the view or its items changes.
visibleItems.at(i)->size()
是与QQuickItem::width()
/QQuickItem::height()
非常相似:
visibleItems.at(i)->size()
is pretty much equivalent to QQuickItem::width()
/QQuickItem::height()
:
inline qreal itemWidth() const { return item ? item->width() : 0; }
inline qreal itemHeight() const { return item ? item->height() : 0; }
据我所见,它或多或少地占用了视图中可见的每个项目的高度(可能等同于当前实例化"),将它们加在一起,然后将其总和除以可见的数量项目.您可以通过添加以下调试输出来确认这一点:
From what I can see, it more or less takes the height of every item that is visible (could probably be equated with "currently instantiated") in the view, adds them together and then divides that sum by the number of visible items. You can confirm this by adding the following debug output:
$ git diff
diff --git a/src/quick/items/qquicklistview.cpp b/src/quick/items/qquicklistview.cpp
index 0351077..acfb88a 100644
--- a/src/quick/items/qquicklistview.cpp
+++ b/src/quick/items/qquicklistview.cpp
@@ -1296,6 +1296,7 @@ void QQuickListViewPrivate::updateAverage()
for (FxViewItem *item : qAsConst(visibleItems))
sum += item->size();
averageSize = qRound(sum / visibleItems.count());
+ qDebug() << "sum" << sum << "visibleItems.count()" << visibleItems.count();
}
qreal QQuickListViewPrivate::headerSize() const
点击某项之前的输出:
qml: estimated contentHeight 5000
sum 550 visibleItems.count() 11
qml: estimated contentHeight 2500
sum 850 visibleItems.count() 17
在按下第一项之后:
sum 850 visibleItems.count() 15
qml: estimated contentHeight 2845
所以我会说
它不使用当前实例的平均大小.
It does not use the average size of the current instances.
在某种程度上是错误的.如果您真的想知道有什么区别,则需要进一步研究代码.
is incorrect to some degree. If you really want to know what the difference is, you'll need to look further into the code.
这篇关于QML ListView如何估计其contentItem的高度/宽度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!