Model-View-Delegate编程框架

【Model-View-Delegate】
首先简单了解MVC。(Qt官方文档对GUI Design的书籍有相关的推荐:详细请看Books about GUI Design)
Model-View-Controller(MVC)是源自SmallTalk的一个设计模式,通常在构建用户界面时使用。在设计模式中写道:MVC由三种对象组成。模型是应用程序对象,视图时其屏幕显示,控制器定义了用户界面对用户输入的反应方式。MVC就是将这三种对象解耦以增加灵活性合复用性。
MVD是在Qt原有MVC的基础上对Controller进行了修改,为了允许灵活地处理用户输入,引入了Delegate的概念,即Model-View-Delegate。框架里有委托的好处在于,它允许自定义呈现和编辑数据项的方式。将数据的可视化模块化,以便我们在开发的过程中可以控制数据的不同方面。可以将列表视图和网格视图交换,而对数据的更改很少,类似地,将数据实例封装在委托中可以使开发人员决定如何呈现或处理数据。(后面我们会通过一个实例来体验此框架的使用)
Qt Quick的MVD框架:
在这里插入图片描述

Model-包含数据与结构,有几种用于创建模型的QML类型
View-显示数据的容器,view可能会展示一个list或者grid数据
Delegate-指示数据应该如何在视图中显示。委托将模型中的每个数据封装起来。可以通过委托访问数据。委托还可以将数据写回可编辑的模型中

对于以上的三部分,每个部分都有抽象类定义,这些抽象类提供了公共接口,并在某些情况下提供了功能的默认实现。我们在开发的过程中就是需要子类化这些抽象类,实现需要的功能。例如:QAbstractItemModel是所有item models的祖先,又衍生了QStringListModel,QStandardItemModel,QAbstractListModel,QAbstractTableModel等; QAbstractItemView是视图类的祖先,衍生了 QListView,QTableView等;QAbstractItemDelegate是Model-View框架中所有Delegates的抽象基类,衍生了 QStyledItemDelegate, QItemDelegate。接下来我们来通过使用QAbstractListModel-ListView-Delegate来体验这个框架的使用

【MVD实操】
1.在qml文件中声明ListView

import QtQuick 2.0

ListView {
  width: 180; height: 200

  model: TestListModel           //model,定义要显示的数据
  delegate: TestDelegate         //delegate,定义数据应该如何显示
}

2.实现Model:继承Qt Model的抽象类QAbstractListModel(它不能直接使用,必须被子类化)

我们会重写三个核心方法支撑向View提供数据

struct TestElem{
    int  testElem1 {1};
    int  testElem2 {2};
    int  testElem3 {3};
};
class TestData
{
public:
    TestData()
    {
        int role = Qt::UserRole;
        m_roleNames.insert(role++,  "testElem1");
        m_roleNames.insert(role++,  "testElem2");
        m_roleNames.insert(role++,  "testElem3");
    }

    ~TestData() {}

    QHash<int, QByteArray> m_roleNames;
    QList<TestElem>        m_testList;
};
class TestModel : public QAbstractListModel
{
    Q_OBJECT
public:
    //返回列表中的项目数
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    //从列表中查找数据
    QVariant data(const QModelIndex &index = QModelIndex(),
                  int role = Qt::DisplayRole) const override;
    //设置角色
    QHash<int, QByteArray> roleNames() const override;
    
    // 添加数据
    bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;
    // 删除数据
    bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex()) override;

private:
    TestData m_testData;
};


int TestModel ::rowCount(const QModelIndex &parent) const
{
    return m_stuData.m_stuList.size();
}

QVariant TestModel ::data(const QModelIndex &index, int role) const
{
    if (index.row() < 0) {
        return QVariant();
    }

    const TestElem &testElem = m_testData.m_testList[index.row()];

    switch (role - Qt::UserRole) {
        case 0:
            return testElem.testElem1;

        case 1:
            return testElem.testElem2;

        case 2:
            return testElem.testElem3;
    }

    return QVariant();
}

QHash<int, QByteArray> TestModel ::roleNames() const
{
    return m_testData.m_roleNames;
}

bool TestModel ::insertRows(int row, int count, const QModelIndex &parent)
{
    beginInsertRows(parent, row, row + count - 1);
    // FIXME: Implement me!
    endInsertRows();
    return true;
}

bool TestModel ::removeRows(int row, int count, const QModelIndex &parent)
{
    beginRemoveRows(parent, row, row + count - 1);
    // FIXME: Implement me!
    endRemoveRows();
    return true;
}

3.实现Delegate

Component{
    id:TestDelegate         
    Rectangle{
        id:delegateRec
        width: 50
        height: 50
        Text{
            id:test1
            text:model.testElem1
        }
        Text{
            id:test2
            text:model.testElem2
        }
        Text{
            id:test3
            text:model.testElem3
        }
    }        
}

会发现,C++的数据已经通过这个模型展示到了qml中,其实这也是C++与qml通信的方式之一(后续会总结C++与qml通信的几种方式);在需求开发的过程中,数据与用户界面的开发是非常独立的,只需要对应好角色名称即可

总结:熟练使用这套框架,会发现自己的代码复用性很高,需求的变动不会带来灾难的开发量,独立的处理好自己的模块即可

参考资料
【1】Qt Assistant model/view Programming
【2】Qt Assistant Models and Views in Qt Quick
【3】Qt Quick核心编程 第十三章 Model/View
【4】开源链接:https://github.com/toby20130333/QtQuickExample
【5】开源链接:https://github.com/foruok/stockMonitor

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一二三o-0-O

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值