QML ListView如何估计其contentItem的高度/宽度 [英] How does the QML ListView estimates the height/width of it's contentItem

查看:745
本文介绍了QML ListView如何估计其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. :)

查看代码,这是设置contentWidthcontentHeight:

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();
}

QQuickListVieworiginPosition()lastPosition()的实现都是 averageSize似乎是该函数由

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆