- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我有一个 QML ProviderItem,它具有返回 QObject 派生对象列表的对象属性。
我想将此列表作为其函数 consumeAll 的属性传递给另一个 QML ConsumerItem。问题是我总是得到空的 QQmlListProperty,所有回调函数都设置为 0,数据指针设置为 0(我认为这些是默认构造的值)
像这样:
ProviderItem.h
class ProviderItem : public QObject, public QQmlParserStatus
{
Q_OBJECT
public:
Q_PROPERTY(QQmlListProperty<QObject> objects READ objects NOTIFY objectsChanged)
QQmlListProperty<QObject> objects();
static int objects_count(QQmlListProperty<QObject> *);
static QObject* objects_at(QQmlListProperty<QObject> *, int);
private:
QList<QObject*> m_objects;
}
ProviderItem.cpp
QQmlListProperty<QObject> ProviderItemPrivate::objects()
{
return QQmlListProperty<QObject>(this, nullptr,
ProviderItem::objects_count,
ProviderItem::objects_at);
}
QObject* ProviderItem::objects_at(QQmlListProperty<QObject> *prop, int index)
{
ProviderItem* provider = qobject_cast<ProviderItem*>(prop->object)
return provider->m_objects.at(index);
}
int ProviderItem::objects_count(QQmlListProperty<QObject> *prop)
{
ProviderItem* provider = qobject_cast<ProviderItem*>(prop->object)
return provider->m_objects.count();
}
ConsumerItem.h
class ConsumerItem: public QObject
{
Q_OBJECT
public:
Q_INVOKABLE void consumeAll(QQmlListProperty<QObject> obj);
};
ConsumerItem.cpp
void ConsumerItem::consumeAll(QQmlListProperty<QObject> obj)
{
qDebug() << obj.count(); // thows exeption as count callback is 0
}
main.qml
Provider {
id: objectProvider
}
Consumer {
id: objectConsumer
}
Connections {
target: objectProvider
onObjectsChanged: {
console.debug(objectProvider.objects) // gives [object Object]
objectConsumer.consumeAll(objectProvider.objects)
var test = objectProvider.objects
console.debug(test) // gives [object Object]
Thermonav.testList(objectProvider.objects)
}
}
显然 ProviderItem 和 ConsumerItem 已注册:
main.cpp
qmlRegisterType<ProviderItem>(uri, major, minor, "Provider");
qmlRegisterType<ConsumerItem>(uri, major, minor, "Consumer");
我也试过:
Q_INVOKABLE void consumeAll(QVariantMap obj);
Q_INVOKABLE void consumeAll(QQmlListProperty<QObject> obj);
Q_INVOKABLE void consumeAll(void* p);
Q_INVOKABLE void consumeAll(QVariant p);
但每次我得到默认构造值。
根据 this article :
When integrating with C++, note that any QQmlListProperty value passed into QML from C++ is automatically converted into a list value, and vice-versa.
所以 qml [object Object] 中的输出在我看来是合法的,因为“列表”不是 js 数据类型。但它也说 QML 列表应该在 QQmlListProperty 中转换回来,这绝对不适合我(或者我做错了)。
我正在使用 Qt 5.12.0
那么如何将在 C++ 中创建的 QQmlListProperty 传递给 QML list,然后再传递给 C++ 中的 QQmlListProperty?
最佳答案
如果您使用 QVariant
并打印:
class ConsumerItem: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE void consumeAll(QVariant objects){
qDebug() << objects;
}
};
你得到:
QVariant(QQmlListReference, )
所以解决方案是使用QQmlListReference
:
class ConsumerItem: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE void consumeAll(const QQmlListReference & objects){
qDebug() << objects.count();
}
};
完整代码:
main.cpp
#include <QtQml>
#include <QtGui>
class Product: public QObject{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged)
public:
Product(const QString & name="", QObject* parent=nullptr):
QObject(parent), m_name(name){}
QString name() const{return m_name;}
void setName(const QString &name){
if(m_name == name) return;
m_name = name;
Q_EMIT nameChanged(m_name);
}
Q_SIGNAL void nameChanged(const QString &);
private:
QString m_name;
};
class ProviderItem: public QObject{
Q_OBJECT
Q_PROPERTY(QQmlListProperty<Product> products READ products NOTIFY productsChanged)
public:
using QObject::QObject;
QQmlListProperty<Product> products(){
return QQmlListProperty<Product>(this, this,
&ProviderItem::appendProduct,
&ProviderItem::productCount,
&ProviderItem::product,
&ProviderItem::clearProducts);
}
void appendProduct(Product* p) {
m_products.append(p);
Q_EMIT productsChanged();
}
int productCount() const{return m_products.count();}
Product *product(int index) const{ return m_products.at(index);}
void clearProducts() {
m_products.clear();
Q_EMIT productsChanged();
}
Q_SIGNAL void productsChanged();
private:
static void appendProduct(QQmlListProperty<Product>* list, Product* p) {
reinterpret_cast<ProviderItem* >(list->data)->appendProduct(p);
}
static void clearProducts(QQmlListProperty<Product>* list) {
reinterpret_cast<ProviderItem* >(list->data)->clearProducts();
}
static Product* product(QQmlListProperty<Product>* list, int i) {
return reinterpret_cast<ProviderItem* >(list->data)->product(i);
}
static int productCount(QQmlListProperty<Product>* list) {
return reinterpret_cast<ProviderItem* >(list->data)->productCount();
}
QVector<Product *> m_products;
};
class ConsumerItem: public QObject
{
Q_OBJECT
public:
using QObject::QObject;
Q_INVOKABLE void consumeAll(const QQmlListReference & products){
for(int i=0; i<products.count(); ++i){
if(Product *product = qobject_cast<Product *>(products.at(i))){
qDebug()<< product->name();
}
}
}
};
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qmlRegisterType<Product>("foo", 1, 0, "Product");
qmlRegisterType<ProviderItem>("foo", 1, 0, "Provider");
qmlRegisterType<ConsumerItem>("foo", 1, 0, "Consumer");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
#include "main.moc"
main.qml
import QtQuick 2.9
import QtQuick.Window 2.2
import foo 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
function create_product(){
var product = Qt.createQmlObject('import foo 1.0; Product {}',
provider,
"dynamicSnippet1");
product.name = "product"+provider.products.length;
provider.products.push(product)
}
Timer {
interval: 1000; running: true; repeat: true
onTriggered: create_product()
}
Provider{
id: provider
onProductsChanged: consumer.consumeAll(provider.products)
products: [
Product{name: "product0"},
Product{name: "product1"},
Product{name: "product2"}
]
}
Consumer{
id: consumer
}
}
关于c++ - 将 QQmlListProperty 作为参数从 QML 传递到 C++,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55047211/
我试图了解人们如何选择使用 QAbstractListModel 还是 QObject 和 QQmlListProperty。 鉴于 QQmlListProperty 处理必须使用 QAbstract
我正在使用 C++ 和 QML 构建一个简单的 Sailfish OS 应用程序。我正在尝试通过 QQmlListProperty 将我的数据库层公开给 QML - 但是我遇到了问题。我可能设置错了
每当我创建 Q_PROPERTY为了以后在 Qml 中使用,我总是创建一个通知信号来告诉 qml 数据已更改并且需要重新评估。 现在有一个 Q_PROPERTY类型 QQmlListProperty我
如果我们想在 QML 中使用自定义 C++ 对象列表,我们可以使用 QQmlListProperty 在 QML 中注册时,我们需要指定一个函数,QML 将使用该函数读取列表。 文档指出,要获得完整的
我正在尝试使用 QQmlListProperty 从 QQuickItem 中公开 QList - 并遵循以下文档: Properties with Object-List Types QQmlLis
如果我有一个包含列表模型 QList (QList) 的类,我将如何将该列表中的模型分配给 QML 中的 ListView ? 类代码: class TreeModel : public QAbstr
我有一个 QML ProviderItem,它具有返回 QObject 派生对象列表的对象属性。 我想将此列表作为其函数 consumeAll 的属性传递给另一个 QML ConsumerItem。问
在文档中明确指出,具有列表的C++类必须继承自QObject,但不清楚列表中的对象是否必须是QObjects。 我试过this使用 QQmlListProperty 和 QQmlListPropert
我是一名优秀的程序员,十分优秀!