本篇文章为大家展示了如何利用上下文属性将 C++ 对象嵌入 QML 里,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
一、设置简单的上下文属性
例如,这里有一个 QML 项,它引用了当前作用域中不存在的 currentDateTime 值:
// MyItem.qmlimport QtQuick 2.0 Text { text: currentDateTime }
这个值可以由加载 QML 组件的 C++ 应用程序使用 QQmlContext::setContextProperty()
直接设置:
QQuickView view; view.rootContext()->setContextProperty("currentDateTime",QDateTime::currentDateTime()); view.setSource(QUrl::fromLocalFile("MyItem.qml")); view.show();
由于在 QML 中计算的所有表达式都是在特定上下文中计算的,如果修改了上下文,则将重新计算该上下文中的所有绑定。因此,应在应用程序初始化之外谨慎使用上下文属性,因为这可能会导致应用程序性能下降。
二、将对象设置为上下文属性
上下文属性可以包含 QVariant
或 QObject*
值。 这意味着也可以使用这种方法注入自定义 C++ 对象,并且可以直接在 QML 中修改和读取这些对象。修改上面的例子,嵌入一个 QObject 实例而不是一个 QDateTime
值,QML 代码在对象实例上调用一个方法:
class ApplicationData : public QObject{ Q_OBJECTpublic: Q_INVOKABLE QDateTime getCurrentDateTime() const { return QDateTime::currentDateTime(); }}; int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); ApplicationData data; QQuickView view; view.rootContext()->setContextProperty("applicationData", &data); view.setSource(QUrl::fromLocalFile("MyItem.qml")); view.show(); return app.exec();}// MyItem.qmlimport QtQuick 2.0 Text { text: applicationData.getCurrentDateTime() }
请注意:从 C++ 返回到 QML 的日期/时间值可以通过 Qt.formatDateTime() 和相关函数进行格式化。
如果 QML 项需要从上下文属性接收信号,它可以使用 Connections
类型连接到它们。 例如,如果 ApplicationData
有一个名为 dataChanged()
的信号,则可以使用 Connections
对象中的 onDataChanged
处理程序连接到该信号:
Text { text: applicationData.getCurrentDateTime() Connections { target: applicationData onDataChanged: console.log("The application data changed!") }}
三、上下文属性与C++ 的数据模型示例
3.1、字符串列表模型
int main(int argc, char ** argv){ QGuiApplication app(argc, argv); QStringList dataList; dataList.append("Item 1"); dataList.append("Item 2"); dataList.append("Item 3"); dataList.append("Item 4"); QQuickView view; QQmlContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); view.setSource(QUrl("qrc:view.qml")); view.show(); return app.exec();}
import QtQuick 2.0 ListView { width: 100; height: 100 model: myModel delegate: Rectangle { height: 25 width: 100 Text { text: modelData } }}
3.2、对象列表模型
#ifndef DATAOBJECT_H#define DATAOBJECT_H #include <QObject> class DataObject : public QObject{ Q_OBJECT Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) Q_PROPERTY(QString color READ color WRITE setColor NOTIFY colorChanged)public: DataObject(QObject *parent=nullptr); DataObject(const QString &name, const QString &color, QObject *parent=nullptr); QString name() const; void setName(const QString &name); QString color() const; void setColor(const QString &color); signals: void nameChanged(); void colorChanged(); private: QString m_name; QString m_color;}; #endif // DATAOBJECT_H
#include <QDebug>#include "dataobject.h" DataObject::DataObject(QObject *parent) : QObject(parent){} DataObject::DataObject(const QString &name, const QString &color, QObject *parent) : QObject(parent), m_name(name), m_color(color){} QString DataObject::name() const{ return m_name;} void DataObject::setName(const QString &name){ if (name != m_name) { m_name = name; emit nameChanged(); }} QString DataObject::color() const{ return m_color;} void DataObject::setColor(const QString &color){ if (color != m_color) { m_color = color; emit colorChanged(); }}#include "dataobject.h" int main(int argc, char ** argv){ QGuiApplication app(argc, argv); QList<QObject*> dataList; dataList.append(new DataObject("Item 1", "red")); dataList.append(new DataObject("Item 2", "green")); dataList.append(new DataObject("Item 3", "blue")); dataList.append(new DataObject("Item 4", "yellow")); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); QQmlContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", QVariant::fromValue(dataList)); view.setSource(QUrl("qrc:view.qml")); view.show(); return app.exec();}import QtQuick 2.0 ListView { width: 100; height: 100 model: myModel delegate: Rectangle { height: 25 width: 100 color: model.modelData.color Text { text: name } }}
3.3、QAbstractItemModel
#include <QAbstractListModel>#include <QStringList> class Animal{public: Animal(const QString &type, const QString &size); QString type() const; QString size() const; private: QString m_type; QString m_size;}; class AnimalModel : public QAbstractListModel{ Q_OBJECTpublic: enum AnimalRoles { TypeRole = Qt::UserRole + 1, SizeRole }; AnimalModel(QObject *parent = nullptr); void addAnimal(const Animal &animal); int rowCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; protected: QHash<int, QByteArray> roleNames() const; private: QList<Animal> m_animals;};
#include "model.h" Animal::Animal(const QString &type, const QString &size) : m_type(type), m_size(size){} QString Animal::type() const{ return m_type;} QString Animal::size() const{ return m_size;} AnimalModel::AnimalModel(QObject *parent) : QAbstractListModel(parent){} void AnimalModel::addAnimal(const Animal &animal){ beginInsertRows(QModelIndex(), rowCount(), rowCount()); m_animals << animal; endInsertRows();} int AnimalModel::rowCount(const QModelIndex & parent) const{ Q_UNUSED(parent) return m_animals.count();} QVariant AnimalModel::data(const QModelIndex & index, int role) const{ if (index.row() < 0 || index.row() >= m_animals.count()) return QVariant(); const Animal &animal = m_animals[index.row()]; if (role == TypeRole) return animal.type(); else if (role == SizeRole) return animal.size(); return QVariant();} QHash<int, QByteArray> AnimalModel::roleNames() const{ QHash<int, QByteArray> roles; roles[TypeRole] = "type"; roles[SizeRole] = "size"; return roles;}int main(int argc, char ** argv){ QGuiApplication app(argc, argv); AnimalModel model; model.addAnimal(Animal("Wolf", "Medium")); model.addAnimal(Animal("Polar bear", "Large")); model.addAnimal(Animal("Quoll", "Small")); QQuickView view; view.setResizeMode(QQuickView::SizeRootObjectToView); QQmlContext *ctxt = view.rootContext(); ctxt->setContextProperty("myModel", &model); view.setSource(QUrl("qrc:view.qml")); view.show(); return app.exec();}
import QtQuick 2.0 ListView{ width: 200; height: 250 model: myModel delegate: Text { text: "Animal: " + type + ", " + size }}
上述内容就是如何利用上下文属性将 C++ 对象嵌入 QML 里,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注编程网行业资讯频道。