具有“填充”过渡的 QML 中继器
Posted
技术标签:
【中文标题】具有“填充”过渡的 QML 中继器【英文标题】:QML Repeater with 'populate' transition 【发布时间】: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
动画?
【问题讨论】:
【参考方案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,但如果您不喜欢这种行为,可以更改它。
【讨论】:
以上是关于具有“填充”过渡的 QML 中继器的主要内容,如果未能解决你的问题,请参考以下文章