如何在QML应用中设计一个C++ Model并使用它
2015-09-09 15:26
1441 查看
我们目前大多数的model是使用ListModel.它是基于QML语言的.虽然我们也可以使用QStringList来做一个简单的Model来供我们的ListView或GridView来使用.对于有些复杂的项目,数据来源于有些算法或来源于互联网,大家可能会基于C++来开发自己的引擎.我们需要把我们得到的数据展现在我们的界面中.利用QML来呈现自己的数据.在今天的例程中,我们尝试利用C++语言来设计一个通用的Model.这个Model将在我们的QML应用中被利用并呈现数据.
在这里,我们定义了一个最基本的数据类型Data.它包含两个数据项type及size.开发者可以根据自己的数据结构来修改这个数据的格式.另外,我们也定义了我们的DataListModel.这是一个我们自己定制的一个数据Model.在这个例程中,我们尽量保持项目简洁,我们并没有利用它来获取一些数据(比如利用C++来解析一个json/xml的文件,网路发来的数据等).大家可以具体参阅文章"D-Pointer".
在这里,我们实现了一个比较完整的Model.我们实现了QAbstractListModel它的一些基本的接口:
我们的main.cpp设计如下:
在这里,我们初始化一些数据到Model里去.在实际的应用中,这个数据可能来源于一些网路请求,甚至是一些socket通信里的数据,或者是解析一些数据库,json/xml等等.
我们的QML设计也非常地简单:
运行我们的应用:
我们可以通过按钮"Add a bear"来添加一个北极熊的图标.我们也可以点击减法符号来删除列表中的一项.
整个项目的源码在:https://github.com/liu-xiao-guo/model
datalistmodel.h
#ifndef DATALISTMODEL_H #define DATALISTMODEL_H #include <QAbstractListModel> #include <QStringList> class Data { public: Data(const QString &type, const QString &size); QString type() const; QString size() const; private: QString m_type; QString m_size; }; class DataListModel : public QAbstractListModel { Q_OBJECT public: enum AnimalRoles { TypeRole = Qt::UserRole + 1, SizeRole1 }; DataListModel(QObject *parent = 0); int rowCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const; Q_INVOKABLE void insert(int index, const Data &data); Q_INVOKABLE void append(const Data &data); Q_INVOKABLE void remove(int index); Q_INVOKABLE void append(const QVariantMap map); signals: void countChanged(int arg); private: int count() const; protected: QHash<int, QByteArray> roleNames() const; private: QList<Data> m_list; }; #endif // DATALISTMODEL_H
在这里,我们定义了一个最基本的数据类型Data.它包含两个数据项type及size.开发者可以根据自己的数据结构来修改这个数据的格式.另外,我们也定义了我们的DataListModel.这是一个我们自己定制的一个数据Model.在这个例程中,我们尽量保持项目简洁,我们并没有利用它来获取一些数据(比如利用C++来解析一个json/xml的文件,网路发来的数据等).大家可以具体参阅文章"D-Pointer".
在这里,我们实现了一个比较完整的Model.我们实现了QAbstractListModel它的一些基本的接口:
int rowCount(const QModelIndex & parent = QModelIndex()) const; QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
datalistmodel.cpp
#include "datalistmodel.h" #include <QDebug> Data::Data(const QString &type, const QString &size) :m_type(type), m_size(size) { } QString Data::type() const { return m_type; } QString Data::size() const { return m_size; } DataListModel::DataListModel(QObject *parent) : QAbstractListModel(parent) { } void DataListModel::insert(int index, const Data &data) { if(index < 0 || index > m_list.count()) { return; } emit beginInsertRows(QModelIndex(), index, index); m_list.insert(index, data); emit endInsertRows(); emit countChanged(m_list.count()); } void DataListModel::remove(int index) { if(index < 0 || index >= m_list.count()) { return; } emit beginRemoveRows(QModelIndex(), index, index); m_list.removeAt( index ); emit endRemoveRows(); emit countChanged(m_list.count()); } void DataListModel::append(const Data &data) { insert(count(), data); } void DataListModel::append(const QVariantMap map) { QString type = map["type"].toString(); QString size = map["size"].toString(); Data data(type, size); insert(count(), data); } int DataListModel::rowCount(const QModelIndex & parent) const { Q_UNUSED(parent); return m_list.count(); } QVariant DataListModel::data(const QModelIndex & index, int role) const { if (index.row() < 0 || index.row() >= m_list.count()) return QVariant(); const Data &data = m_list[index.row()]; // qDebug() << "row: " << index.row(); if (role == TypeRole) return data.type(); else if (role == SizeRole1) return data.size(); return QVariant(); } QHash<int, QByteArray> DataListModel::roleNames() const { QHash<int, QByteArray> roles; roles[TypeRole] = "type"; roles[SizeRole1] = "size"; return roles; } int DataListModel::count() const { return rowCount(QModelIndex()); }
datalistmodel.cpp
#include "datalistmodel.h" #include <QDebug> Data::Data(const QString &type, const QString &size) :m_type(type), m_size(size) { } QString Data::type() const { return m_type; } QString Data::size() const { return m_size; } DataListModel::DataListModel(QObject *parent) : QAbstractListModel(parent) { } void DataListModel::insert(int index, const Data &data) { if(index < 0 || index > m_list.count()) { return; } emit beginInsertRows(QModelIndex(), index, index); m_list.insert(index, data); emit endInsertRows(); emit countChanged(m_list.count()); } void DataListModel::remove(int index) { if(index < 0 || index >= m_list.count()) { return; } emit beginRemoveRows(QModelIndex(), index, index); m_list.removeAt( index ); emit endRemoveRows(); emit countChanged(m_list.count()); } void DataListModel::append(const Data &data) { insert(count(), data); } void DataListModel::append(const QVariantMap map) { QString type = map["type"].toString(); QString size = map["size"].toString(); Data data(type, size); insert(count(), data); } int DataListModel::rowCount(const QModelIndex & parent) const { Q_UNUSED(parent); return m_list.count(); } QVariant DataListModel::data(const QModelIndex & index, int role) const { if (index.row() < 0 || index.row() >= m_list.count()) return QVariant(); const Data &data = m_list[index.row()]; // qDebug() << "row: " << index.row(); if (role == TypeRole) return data.type(); else if (role == SizeRole1) return data.size(); return QVariant(); } QHash<int, QByteArray> DataListModel::roleNames() const { QHash<int, QByteArray> roles; roles[TypeRole] = "type"; roles[SizeRole1] = "size"; return roles; } int DataListModel::count() const { return rowCount(QModelIndex()); }
我们的main.cpp设计如下:
#include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQuickView> #include <QQmlContext> #include "datalistmodel.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); DataListModel model; model.append( Data("wolf.jpg", "Medium") ); model.append( Data("polarbear.jpg", "Large") ); model.append( Data("quoll.jpg", "Small") ); QQuickView view; view.setSource(QUrl(QStringLiteral("qrc:///Main.qml"))); view.setResizeMode(QQuickView::SizeRootObjectToView); view.rootContext()->setContextProperty("myModel", &model); view.show(); return app.exec(); }
在这里,我们初始化一些数据到Model里去.在实际的应用中,这个数据可能来源于一些网路请求,甚至是一些socket通信里的数据,或者是解析一些数据库,json/xml等等.
我们的QML设计也非常地简单:
Main.qml
import QtQuick 2.0 import Ubuntu.Components 1.1 /*! \brief MainView with a Label and Button elements. */ MainView { // objectName for functional testing purposes (autopilot-qt5) objectName: "mainView" // Note! applicationName needs to match the "name" field of the click manifest applicationName: "model.liu-xiao-guo" /* This property enables the application to change orientation when the device is rotated. The default is false. */ //automaticOrientation: true // Removes the old toolbar and enables new features of the new header. useDeprecatedToolbar: false width: units.gu(60) height: units.gu(85) Page { title: i18n.tr("model") ListView { id: listview clip: true width: parent.width height: parent.height - button.height model: myModel delegate: Item { id: delegate width: listview.width height: units.gu(20) Row { spacing: units.gu(2) Image { source: "images/" + type height: delegate.height *.9 width: height } Text { anchors.verticalCenter: parent.verticalCenter text: size font.pixelSize: units.gu(5) color: "red" } } Image { width: units.gu(4) height: width anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.rightMargin: units.gu(1) source: "images/remove.png" MouseArea { anchors.fill: parent onClicked: { myModel.remove(index); } } } } } Button { id: button anchors.bottom: parent.bottom anchors.bottomMargin: units.gu(2) anchors.horizontalCenter: parent.horizontalCenter text: "Add a bear" onClicked: { // We are going to add a bear to the list var o = { "type" : "polarbear.jpg", "size" : "large" }; myModel.append( o ); listview.positionViewAtEnd() } } } }
运行我们的应用:
我们可以通过按钮"Add a bear"来添加一个北极熊的图标.我们也可以点击减法符号来删除列表中的一项.
整个项目的源码在:https://github.com/liu-xiao-guo/model
相关文章推荐
- 设计模式C++实现3——适配器模式
- C语言之函数调用
- 写一个只能C编译通过,而C++不能编译通过的函数。
- 你不知道的c语言之为什么数组的大小不能是变量
- C风格字符串和C++string对象的相互转化
- ‘this’ pointer in C++
- [C++11 并发编程] 17 超时等待 - clock和duration
- C++在本地路径下创建一个文件
- 【C++11】final, override,重载,重写覆盖,重写隐藏
- 【C++专题】static_cast, dynamic_cast, const_cast探讨
- C++构造函数的继承
- 深入浅出UML类图二
- C++类
- 计算一个整数有多少个1的函数
- Java 的 interface、abstract class 与 C++ 的多继承、虚基类
- c++ 副本构造器
- 深入浅出UML类图一
- C++——运算符重载(三)
- C++中智能指针的设计和使用
- [iOS开发]C语言-04-程序循环结构(while{})视频解说