Using C++ Models in QML

    xiaoxiao2022-07-13  163

    参考youtube上qt官方的视频:https://www.youtube.com/watch?v=9BcAYDlpuT8 youtube视频下方本来有github地址的,进去后代码为空,就照着视频教程把代码重新敲了一遍。 视频我下载下来了,1080p的,自己敲的代码也打包了,百度云盘: 链接:https://pan.baidu.com/s/1BGfC0WLY7u0ZLab0TYtwLQ 提取码:ji42 如果失效了,麻烦留言。 (我csdn没资源积分了,麻烦分多或者会员的大佬,下载我上传的资源,赏我点积分,非常感谢!) https://download.csdn.net/download/hp_cpp/11197399 (plus,本来想设置成1积分的,结果发现没法设置资源积分,csdn居然还在偷偷涨资源积分,看来要转github这样的平台了(⊙o⊙)…)

    本教程主要功能 1.实现了一个简单的待办事项 2.删除勾选的一行记录,也可以删除多行已经勾选的记录 是用C++继承QAbstractListModel实现了model,然后给qml调用。 运行效果: 源码之前了无秘密: ToDoList.qml

    import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.3 import ToDo 1.0 ColumnLayout { Frame { ListView { implicitWidth: 250 implicitHeight: 250 clip: true /* model: ListModel { ListElement { done: true description: "Wash the car" } ListElement { done: true description: "fix the sink" } } */ model: ToDoModel { list: toDoList } delegate: RowLayout { width: parent.width CheckBox { checked: model.done onClicked: model.done = checked } TextField { text: model.description onEditingFinished: model.description = text Layout.fillWidth: true } } } } RowLayout { Button { text: qsTr("Add new item") onClicked: toDoList.appendItem() Layout.fillWidth: true } Button { text: qsTr("Remove completed") onClicked: toDoList.removeCompleteItems() Layout.fillWidth: true } } }

    main.qml文件:

    import QtQuick 2.9 import QtQuick.Window 2.2 Window { visible: true width: 640 height: 480 title: qsTr("Hello World") ToDoList { anchors.centerIn: parent } }

    todolist.h文件:

    #ifndef TODOLIST_H #define TODOLIST_H #include <QObject> #include <QVector> struct ToDoItem { bool done; QString description; }; class ToDoList : public QObject { Q_OBJECT public: explicit ToDoList(QObject *parent = nullptr); QVector<ToDoItem> items() const; bool setItemAt(int index, const ToDoItem &item); signals: void preItemAppended(); void postItemAppended(); void preItemRemoved(int index); void postItemRemoved(); public slots: void appendItem(); void removeCompleteItems(); private: QVector<ToDoItem> mItems; }; #endif // TODOLIST_H

    todolist.cpp文件:

    #include "todolist.h" ToDoList::ToDoList(QObject *parent) : QObject(parent) { mItems.append({true, QStringLiteral("Wash the car")}); mItems.append({true, QStringLiteral("Fix the car")}); } QVector<ToDoItem> ToDoList::items() const { return mItems; } bool ToDoList::setItemAt(int index, const ToDoItem &item) { if (index < 0 || index >= mItems.size()) return false; const ToDoItem &oldItem = mItems.at(index); if (item.done == oldItem.done && item.description == oldItem.description) return false; mItems[index] = item; return true; } void ToDoList::appendItem() { emit preItemAppended(); ToDoItem item; item.done = false; mItems.append(item); emit postItemAppended(); } void ToDoList::removeCompleteItems() { for (int i = 0; i < mItems.size(); ) { if (mItems.at(i).done) { emit preItemRemoved(i); mItems.removeAt(i); emit postItemRemoved(); } else { ++i; } } }

    todomodel.h文件:

    #ifndef TODOMODEL_H #define TODOMODEL_H #include <QAbstractListModel> class ToDoList; class ToDoModel : public QAbstractListModel { Q_OBJECT Q_PROPERTY(ToDoList *list READ list WRITE setList) public: explicit ToDoModel(QObject *parent = nullptr); enum { DoneRole = Qt::UserRole, DescriptionRole }; // Basic functionality: int rowCount(const QModelIndex &parent = QModelIndex()) const override; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; // Editable: bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; Qt::ItemFlags flags(const QModelIndex& index) const override; virtual QHash<int, QByteArray> roleNames() const override; ToDoList *list() const; void setList(ToDoList *list); private: ToDoList *mList; }; #endif // TODOMODEL_H

    todomodel.cpp文件:

    #include "todomodel.h" #include "todolist.h" ToDoModel::ToDoModel(QObject *parent) : QAbstractListModel(parent) , mList(nullptr) { } int ToDoModel::rowCount(const QModelIndex &parent) const { // For list models only the root node (an invalid parent) should return the list's size. For all // other (valid) parents, rowCount() should return 0 so that it does not become a tree model. if (parent.isValid() || !mList) return 0; // FIXME: Implement me! return mList->items().size(); } QVariant ToDoModel::data(const QModelIndex &index, int role) const { if (!index.isValid() || !mList) return QVariant(); // FIXME: Implement me! const ToDoItem item = mList->items().at(index.row()); switch (role) { case DoneRole: return QVariant(item.done); case DescriptionRole: return QVariant(item.description); } return QVariant(); } bool ToDoModel::setData(const QModelIndex &index, const QVariant &value, int role) { if (!mList) return false; ToDoItem item = mList->items().at(index.row()); switch (role) { case DoneRole: item.done = value.toBool(); break; case DescriptionRole: item.description = value.toString(); break; } if (mList->setItemAt(index.row(), item)) { // FIXME: Implement me! emit dataChanged(index, index, QVector<int>() << role); return true; } return false; } Qt::ItemFlags ToDoModel::flags(const QModelIndex &index) const { if (!index.isValid()) return Qt::NoItemFlags; return Qt::ItemIsEditable; // FIXME: Implement me! } QHash<int, QByteArray> ToDoModel::roleNames() const { QHash<int, QByteArray> names; names[DoneRole] = "done"; names[DescriptionRole] = "description"; return names; } ToDoList *ToDoModel::list() const { return mList; } void ToDoModel::setList(ToDoList *list) { beginResetModel(); if (mList) mList->disconnect(this); mList = list; if (mList) { connect(mList, &ToDoList::preItemAppended, this, [=](){ const int index = mList->items().size(); beginInsertRows(QModelIndex(), index, index); }); connect(mList, &ToDoList::postItemAppended, this, [=](){ endInsertRows(); }); connect(mList, &ToDoList::preItemRemoved, this, [=](int index){ beginRemoveRows(QModelIndex(), index, index); }); connect(mList, &ToDoList::postItemRemoved, this, [=](){ endRemoveRows(); }); } endResetModel(); }

    main.cpp文件:

    #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "todomodel.h" #include "todolist.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); qmlRegisterType<ToDoModel>("ToDo", 1, 0, "ToDoModel"); qmlRegisterUncreatableType<ToDoList>("ToDo", 1, 0, "toDoList", QStringLiteral("ToDoLsit should not be created in QML")); ToDoList toDoList; QQmlApplicationEngine engine; engine.rootContext()->setContextProperty(QStringLiteral("toDoList"), &toDoList); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); if (engine.rootObjects().isEmpty()) return -1; return app.exec(); }

    其中class ToDoModel : public QAbstractListModel 利用qt creator进行添加比较方便: 视频中是勾选的第三个,其余的可以根据需要勾选。 利用代码补齐,选中mList后,用Alt+Enter可以自动添以下两个函数: ToDoList *list() const; void setList(ToDoList *list); 然后发现其他人也看过这个视频,参考: https://blog.csdn.net/qq_32768743/article/details/80863753 官方文档:https://doc.qt.io/qt-5/qtquick-modelviewsdata-cppmodels.html 纯QML写的:https://blog.csdn.net/suerimn/article/details/86141903

    最新回复(0)