【问题标题】:QML Repeater with 'populate' transition具有“填充”过渡的 QML 中继器
【发布时间】:2021-09-26 16:05:26
【问题描述】:

我正在尝试使用中继器复制ListView.populate: Transition {..}。不幸的是,由于可怕的性能问题,我不能简单地使用ListView,所以只能使用Repeater

我正在寻找的过渡很简单,实际上正是 ListView Documentation 中使用的过渡,即我的中继器加载时,每个条目从顶部 Here is a working example of my desired outcome 向下“级联”

我尝试让我们使用Behavior on y {NumberAnimation {duration: 300} },但是中继器似乎没有在创建时修改y。我还将它绑定到 Component.onCompleted 处理程序中,以查看它也触发了但失败了。

我的问题是

如何为Repeater 创建类似于ListView.populate 属性的y 动画?

【问题讨论】:

    标签: qt qml repeater


    【解决方案1】:

    显而易见的替代方法是将 QML Column 与 Repeater 一起使用,但 Column 是一个定位器,将直接设置其子级 y 位置而不使用 setProperty。出于这个原因,我做了类似的事情,但这次让 QML 系统知道属性更改。

    MyColumn.h

    #pragma once
    
    #include <QQuickItem>
    
    class MyColumn : public QQuickItem
    {
        Q_OBJECT
    
        Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing NOTIFY spacingChanged)
    
    public:
        explicit MyColumn(QQuickItem* parent = nullptr);
        ~MyColumn();
    
        qreal spacing() const;
        void setSpacing(qreal r);
    
        void positionItems();
        void componentComplete() override;
        void itemChange(ItemChange, const ItemChangeData&) override;
    
    Q_SIGNALS:
        void spacingChanged();
    
    public /*slots*/:
        void onChildImplicitWidthChanged();
        void onChildImplicitHeightChanged();
    
    private:
        qreal mSpacing;
    };
    

    MyColumn.cpp

    #include "MyColumn.h"
    
    MyColumn::MyColumn(QQuickItem* parent) : QQuickItem{ parent }, mSpacing{ 0.0 }
    {
        setFlag(ItemHasContents, true);
    }
    
    MyColumn::~MyColumn()
    {
    }
    
    qreal MyColumn::spacing() const
    {
        return mSpacing;
    }
    
    void MyColumn::setSpacing(qreal s)
    {
        if (mSpacing == s) return;
        mSpacing = s;
    
        Q_EMIT spacingChanged();
    
        if (isComponentComplete())
            positionItems();
    }
    
    void MyColumn::positionItems()
    {
        qreal maxImplicitWidth = 0.0;
        qreal totalImplicitHeight = 0.0;
    
        QList<QQuickItem*> children = childItems();
        for (int i = 0; i < children.count(); ++i) {
            QQuickItem* child = children.at(i);
    
            //child->setY(totalImplicitHeight);
            child->setProperty("y", totalImplicitHeight);
    
            if (child->implicitWidth() > maxImplicitWidth)
                maxImplicitWidth = child->implicitWidth();
            if (child->implicitHeight() > 0) {
                totalImplicitHeight += child->implicitHeight();
                totalImplicitHeight += mSpacing;
            }
        }
    
        totalImplicitHeight -= mSpacing;
    
        setImplicitWidth(maxImplicitWidth);
        setImplicitHeight(totalImplicitHeight);
    }
    
    void MyColumn::componentComplete()
    {
        positionItems();
        QQuickItem::componentComplete();
    }
    
    void MyColumn::onChildImplicitWidthChanged()
    {
        positionItems();
    }
    
    void MyColumn::onChildImplicitHeightChanged()
    {
        positionItems();
    }
    
    void MyColumn::itemChange(ItemChange change, const ItemChangeData& value)
    {
        if (change == ItemChildAddedChange)
        {
            QObject::connect(value.item, &QQuickItem::implicitWidthChanged, this, &MyColumn::onChildImplicitWidthChanged);
            QObject::connect(value.item, &QQuickItem::implicitHeightChanged, this, &MyColumn::onChildImplicitHeightChanged);
        }
        else if(change == ItemChildRemovedChange)
        {
            positionItems();
        }
        QQuickItem::itemChange(change, value);
    }
    

    例如,在 main.cpp 中,您必须将此类型注册为 QML 中的可创建类型

    qmlRegisterType<MyColumn>("MyColumn", 1, 0, "MyColumn");
    

    这里是相关的QML代码sn-p:

    //...
    import MyColumn 1.0
    //...
    MyColumn {
        Repeater {
            model: 10
            Rectangle {
                implicitWidth: 200
                implicitHeight: 30
                color: "red"
                border.width: 1
                Behavior on y { NumberAnimation { duration: 1000; easing.type: Easing.OutQuad; } }
            }
        }
    }
    

    请注意,我的实现适用于implicitWidth,但如果您不喜欢这种行为,可以更改它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-02-28
      • 2013-12-19
      • 1970-01-01
      • 2013-02-17
      • 2015-12-09
      • 1970-01-01
      • 2019-08-13
      • 2016-03-12
      相关资源
      最近更新 更多