Qt6教程之三(5) Model/View

Model-View是一项通用的技术框架,不是Qt独有的,很多的编程语言均有model-view的实现。

model-view是模型-视图的含义,其中模型属于业务逻辑层,同时模型与数据源实时绑定。视图用于显示数据,同时负责与用户的交互。当用户在视图层操作时,模型层实现各种响应逻辑,并及时把数据源更新。

在Qt中,实际上还有一个代理(delegate)角色,代理功能可以让用户定制数据的界面显示和编辑方式。所以完整的架构简称MVD (Model-View-Delegate)。

模型、视图和代理之间使用信号和槽通信。当源数据发生变化时,数据模型发射信号通知视图组件;当用户在界面上操作数据时,视图组件发射信号表示这些操作信息;当编辑数据时,代理发射信号告知数据模型和视图组件编辑器的状态。
所有的基于项数据的数据模型(Model) 都是基于QAbstractItemModel 类的,这个类定义了视图组件和代理存取数据的接口。数据无需存储再数据模型里,数据可以是其他类、文件、数据库或任何数据源。

Qt 中与数据模型相关的几个主要的类的层次结构如图 2 所示:


视图组件(View)是显示数据模型的数据的界面组件,Qt 提供的视图组件有:

QListView:用于显示单列的列表数据,适用于一维数据的操作。
QTreeView:用于显示树状结构数据,适用于树状结构数据的操作。
QTableView:用于显示表格状数据,适用于二维表格型数据的操作。
QColumnView:用多个QListView显示树状层次结构,树状结构的一层用一个QListView显示。
QHeaderView:提供行表头或列表头的视图组件,如QTableView的行表头和列表头。

关于以上几个视图组件的使用在前面的博客中有介绍,需要了解的朋友请转至:Qt6教程之二(4) item views_爱折腾的业余程序员的博客-CSDN博客本节主要讲解Qt的项目视图!https://blog.csdn.net/XiaoWang_csdn/article/details/129070847

模型索引(model index)

为了保证数据的表示与数据存取方式隔离,数据模型中引入了模型索引的概念。通过数据模型存取的每个数据都有一个模型索引,视图组件和代理都通过模型索引来获取数据。

QModelIndex 表示模型索引的类。模型索引提供数据存取的一个临时指针,用于通过数据模型提取或修改数据。因为模型内部组织数据的结构随时可能改变,所以模型索引是临时的。如果需要使用持久性的模型索引,则要使用 QPersistentModelIndex 类。
 

上面是对Qt的MVD架构的简单介绍,下面我们来做一个使用默认代理和使用自定义代理的示例,视图使用QListView,模型使用QStringListModel ,。

话不多说,开始敲代码:

新建一个新的工程叫test_QListViewDemo,不需要ui文件,

使用默认代理,就在mainwindow.cpp中写几行代码,其他保持不变,代码非常简单,如下:

mainwindow.cpp

#include "mainwindow.h"
#include<QVBoxLayout>
#include<QListView>
#include<QStringListModel>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    resize(900,900);
    setWindowTitle("listView");


    QVBoxLayout *vl=new QVBoxLayout(this);

    QStringList list;
    list<<"hello world" <<"hello listView"<<"hello listModel";

    QStringListModel *listModel=new QStringListModel;
    listModel->setStringList(list);

    QListView *view=new QListView(this);
    view->setModel(listModel);

    view->resize(800,800);

    vl->addWidget(view);
    setLayout(vl);

    //view->show();
}

MainWindow::~MainWindow()
{
}

运行效果:

使用自定义代理实现:

新建一个代理类,叫MyDelegate ,头文件代码:
MyDelegate.h



#ifndef MYDELEGATE_H
#define MYDELEGATE_H

#include <QItemDelegate>

class MyDelegate : public QItemDelegate
{
    Q_OBJECT

public:
    MyDelegate(QWidget *parent = nullptr);
    QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
    void setEditorData(QWidget *editor, const QModelIndex &index) const;
    void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const;
    void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const;

};

#endif // MYDELEGATE_H

MyDelegate.cpp

#include "mydelegate.h"

#include <QPainter>
#include <QPainterPath>
#include<QLineEdit>



MyDelegate::MyDelegate(QWidget *parent) : QItemDelegate(parent)
{

}

//提供编辑器
QWidget *MyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QLineEdit *lineEdit=new QLineEdit(parent);
    lineEdit->setText("please inpit text");

    return lineEdit;
}

//将Model数据复制到编辑器里
void MyDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
    QString text = index.model()->data(index, Qt::EditRole).toString();
    QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
    lineEdit->setText(text);
}

//提交数据给模型
void MyDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
    QString text = lineEdit->text();
    model->setData(index, text, Qt::EditRole);

}

//更新编辑器几何外形
void MyDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{

    editor->setGeometry(option.rect);
}


最后,把我们自定义的委托安装到当前视图中,只需要在mainwindow.cpp中加一行代码:

view->setItemDelegate(new MyDelegate());

mainwindow.cpp完整代码:

#include "mainwindow.h"
#include<QVBoxLayout>
#include<QListView>
#include<QStringListModel>
#include <mydelegate.h>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{

    resize(900,900);
    setWindowTitle("listView");


    QVBoxLayout *vl=new QVBoxLayout(this);

    QStringList list;
    list<<"hello world" <<"hello listView"<<"hello listModel";

    QStringListModel *listModel=new QStringListModel;
    listModel->setStringList(list);

    QListView *view=new QListView(this);
    view->setModel(listModel);
    view->setItemDelegate(new MyDelegate());

    view->resize(800,800);

    vl->addWidget(view);
    setLayout(vl);

    //view->show();
}

MainWindow::~MainWindow()
{
}

 此时,当双击编辑单行文本时,会自动提供一个单行文本编辑框,效果如下:

 

上一篇文章:

Qt6教程之三(4) 页面控件布局_爱折腾的业余程序员的博客-CSDN博客主要介绍Qt的控件布局,包括单布局、嵌套布局的示例!https://blog.csdn.net/XiaoWang_csdn/article/details/129336845

下一篇文章:

Qt6教程之三(6) 界面自绘与绘图类_爱折腾的业余程序员的博客-CSDN博客界面绘制与绘图类介绍!https://blog.csdn.net/XiaoWang_csdn/article/details/129342923

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Qt中的Model/View是一种基于MVC(Model-View-Controller)设计模式的实现方式。Model/View架构将数据的存储和显示分离开来,使得程序的结构更加清晰,并且可以提高程序的可维护性和可扩展性。 在Qt中,Model/View是面向对象的。它由三个基础类组成:QAbstractItemModel、QAbstractTableModel和QAbstractListModel。QAbstractItemModel为QAbstractTableModel和QAbstractListModel提供了接口规范,使用它可以将数据模型与View分离开来。QAbstractTableModel主要为表格型数据模型定义了一套标准。QAbstractListModel与之类似,为列表型数据模型定义了一套标准。 在Model/View中,Model提供了从数据源中获取数据并将其封装成数据项及其属性的方式。而View根据Model提供的数据项及其属性,对其进行可视化展示。对于数据的修改和删除等操作,则通过View传递给Model来进行实现。 Model的数据来源可以是任何类型的数据,例如数据库、XML文件、内存中的数据等等。ModelView之间的通信是通过信号和槽机制来实现的。当Model的数据发生变化时,它会发出数据变化的信号,View会从这些信号中得知数据发生了哪些改变,然后对其进行更新。 Model/View提供了一种灵活、高效、可扩展的方案来处理数据。在Qt中,开发者可以使用其提供的各种ModelView类,或者继承这些类来实现自己的数据模型和视图类,以便更好地满足自己的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值