Using C++ Models in QML
作者:互联网
参考youtube上qt官方的视频:https://www.youtube.com/watch?v=9BcAYDlpuT8
youtube视频下方本来有github地址的,进去后代码为空,就照着视频教程把代码重新敲了一遍。
主要功能
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
标签:index,const,item,Models,return,mList,ToDoList,QML,Using 来源: https://blog.csdn.net/hp_cpp/article/details/90486676