如何使用Q_PROPERTY

时间:2018-10-16 11:52:41

标签: c++ qt qml qt5

我有一个非常简单的类,具有2个属性;键和值:

KeyValue.h:

class KeyValue : public QObject
{
  Q_OBJECT
  Q_PROPERTY(QString key READ getKey WRITE setKey NOTIFY keyChanged)
  Q_PROPERTY(QString value READ getValue WRITE setValue NOTIFY valueChanged)

 public:
  KeyValue(const QString& key, const QString& value, QObject* parent = 0);  

 signals:
  void keyChanged();
  void valueChanged();

 private:
  QString _key;
  QString _value;

  QString getKey() const;
  QString getValue() const;

  void setKey(const QString& key);  
  void setValue(const QString& value);
};
Q_DECLARE_METATYPE(KeyValue)

在另一个类中,我想要一个包含KeyValue对象列表的属性,因此我可以将此列表用作QML中的模型。

Controller.h

class Controller : public QObject
{
  Q_OBJECT
  Q_PROPERTY(QList<KeyValue*> items READ getItems NOTIFY itemsChanged)

 public:
  explicit Controller(QObject* parent = 0);

 signals:
  void itemsChanged(); 

 private:
  QList<KeyValue*> getItems() const;
};

我希望能够通过以下方式在QML中使用它:

import QtQuick 2.7
import customqml 1.0

Item{
  Controller{
    id: controller
  }
  Repeater{
    model: controller.items
    Text{
      text: modelData.key + ": " + modelData.value
    }
  }
}

两个类都注册在我的main.cpp文件中:

qmlRegisterType<KeyValue>("customqml", 1, 0, "KeyValue");
qmlRegisterType<Controller>("customqml", 1, 0, "Controller");

上面的代码不起作用,因为我显然无法直接将QList公开给QML。我曾尝试使用QAbstractItemModel和QQmlListProperty,但无法使其正常工作。谁能指出我正确的方向?

我的主要问题是Controller类中 items 属性的类型和 getItems 方法的返回值。

我正在使用Qt 5.9(如果有什么区别)。

2 个答案:

答案 0 :(得分:4)

注意:

  • getter和setter通常是公共的,除了例外,请将其移到公共部分

  • 从QObject继承的类不需要QMetaType,因为当您要传输该类的数据时,将使用指针。

QML不能通过Q_PROPERTY支持所有数据类型,因此可能的解决方案是通过已知的类导出,例如

  • QList<QObject *>

class Controller : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QList<QObject *> items READ getItems NOTIFY itemsChanged)
public:
    explicit Controller(QObject *parent = nullptr);
    QList<QObject *> getItems() const;
signals:
    void itemsChanged();
private:
    QList<KeyValue *>key_values_list;
};

...
QList<QObject *> Controller::getItems() const
{
    QObjectList l;
    for(auto e: key_values_list)
        l << e;
    return l;
}
  • QVariantList

class Controller : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QVariantList items READ getItems NOTIFY itemsChanged)
public:
    explicit Controller(QObject *parent = nullptr);
    QVariantList getItems() const;
signals:
    void itemsChanged();
private:
    QList<KeyValue *>key_values_list;
};

...
QVariantList Controller::getItems() const
{
    QVariantList l;
    for(auto e: key_values_list)
        l.append(QVariant::fromValue(e));
    return l;
}

其他选项是实现模型,下面的示例仅显示只读模型:

keyvaluemodel.h

#ifndef KEYVALUEMODEL_H
#define KEYVALUEMODEL_H

#include "keyvalue.h"

#include <QAbstractListModel>

class KeyValueModel : public QAbstractListModel
{
    Q_OBJECT

public:
    explicit KeyValueModel(QObject *parent = nullptr)
        : QAbstractListModel(parent)
    {
        key_values_list = {new KeyValue{"k", "v"}, new KeyValue{"k2", "v2"}};
    }
    int rowCount(const QModelIndex &parent = QModelIndex()) const override
    {
        if (parent.isValid())
            return 0;
        return key_values_list.length();
    }
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override
    {
        if (!index.isValid())
            return QVariant();
        if(index.row() >= 0 && index.row() < rowCount())
            return QVariant::fromValue(key_values_list[index.row()]);
        return QVariant();
    }
private:
    QList<KeyValue* >key_values_list;
};

#endif // KEYVALUEMODEL_H

class Controller : public QObject
{
    Q_OBJECT
    Q_PROPERTY(KeyValueModel* items READ getItems NOTIFY itemsChanged)
public:
    explicit Controller(QObject *parent = nullptr);
    KeyValueModel* getItems() const;
signals:
    void itemsChanged();
private:
    KeyValueModel *model;
};

...
Text{
    text: display.key + ": " + display.value
}
...

通过类似的方法,您可以实现QQmlListProperty,在文档中有很多示例。

答案 1 :(得分:0)

如果您想要一个具有添加/删除对象和更改数据的复杂模型,则应考虑使用子类QAbstractListModel

以一种简单但不太灵活的方式,您可以使用QVariantList并将Controller类设为值类型。您需要:

  • 控制器头文件末尾的宏Q_DECLARE_METATYPE(Controller)。
  • 控制器的副本构造器
  • 控制器的默认构造函数

Q_PROPERTY类型和返回值就是QVariantList。