Qt模型/视图框架(一)

简介: Qt模型/视图框架(一)

模型视图框架其主要目的就是将数据与界面分开,起初可能会有不少小伙伴觉得不是很好理解,但在不断的深入和学习中,会慢慢掌握并理解。一旦你掌握了它,你会觉得这很简单,而且还很实用。

下面,就跟大家分享下Qt中的MVC。

在传统的Widgets应用程序中,Qt并没有将数据和窗口分开,显然这样的工作就留给了用户。而Qt的MVC框架则是将界面与数据进行了隔离,VIEW(视图)负责展示数据,MODEL(模型)负责管理数据,DELEGATE(委托)负责VIEW和MODEL的交互。

也许,有的同学看了Qt的帮助文档,洋洋洒洒一大堆,最后也看的是云里雾里,小豆君在这里就以一个简单的例子来帮助大家理解Qt中的MVC如何操作的,好让大家有个初步的认识。

1 数据和窗口在一起的困境

有这样一个需求,需要将某个班级的学生以列表的形式展示出来,并且可以向班级中添加学生。

1.1 首先创建两个类,我用StudentClass表示班级,用Student表示学生。

//学生类
class Student
{
public:
    QString getId() const;
    void setId(const QString &value);
    QString getName() const;
    void setName(const QString &value);
    //判断该学生是否有效,学号和姓名都不能为空
    bool isValid() const
    {
        return !id.isEmpty() && !name.isEmpty();
    }
private:
    QString id;     //学生学号
    QString name;   //姓名
};
//班级类
class StudentClass
{
public:
    QString getId() const;
    void setId(const QString &value);
    QString getName() const;
    void setName(const QString &value);
    //为班级添加一个新同学
    bool add(const Student& student)
    {
        bool success = false;
        if (student.isValid())
        {
            if (!studentMap.contains(student.getId()))
            {
                studentMap.insert(student.getId(), student);
                success = true;
            }
        }
        return success;
    }
    //获取学生列表
    QList<Student> getStudentList() const
    {
        return studentMap.values();
    }
private:
    QString id;  //班级id
    QString name;//班级名称
    QMap<QString, Student> studentMap;//key-学生学号
};


1.2 接下来,创建一个窗口用来展示学生姓名列表,并且可以录入学生学号和姓名,添加学生。该窗口类中保存了班级信息。



namespace Ui {
class StudentsWidget;
}
//学生列表窗口
class StudentsWidget : public QWidget
{
    Q_OBJECT
public:
    explicit StudentsWidget(QWidget *parent = 0);
    ~StudentsWidget();
private slots:
    void on_pushButton_clicked();
private:
    Ui::StudentsWidget *ui;
    StudentClass studentClass;//保存有班级数据
};


添加学生的槽函数实现:

void StudentsWidget::on_pushButton_clicked()
{
    QString id   = ui->line_studentid->text();
    QString name = ui->line_name->text();
    Student student;
    student.setId(id);
    student.setName(name);
    if (studentClass.add(student))
    {
        ui->listWidget->addItem(student.getName());
    }
}


1.3 好了,我们运行程序,窗口可以方便的添加学生。



1.4 可恶的是,现在需求改变了,客户提出要再创建一个表格来展示学生的姓名和所属班级。为此,你不得不在studentClass成功添加学生后,为列表和表格控件分别添加一个对应的QListWidgetItem和QTableWidgetItem。

当然,如果只有这么两个控件需要修改,这样的事情也不算多繁琐,但是你防不住客户有更多的需求,例如他需要更多不同的表格对班级或学生数据进行展示或更改,如果一个一个改将会是一件令人抓狂的事情,并且极易出错。

2 使用MVC解决问题

为了解决这个问题,我们来采用MVC的办法,直接看代码。

2.1 首先在StudentsWidget的私有类中添加一个model成员变量,一般情况下,都会以QStandardItemModel类作为视图的model。

private:
    Ui::StudentsWidget *ui;
    StudentClass studentClass;//保存有班级数据
    QStandardItemModel* model;


2.2 修改构造函数

StudentsWidget::StudentsWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::StudentsWidget)
{
    ui->setupUi(this);
    studentClass.setId("1");
    studentClass.setName("1班");
    //为model设置标题
    QStringList headers;
    headers << "姓名" << "所属班级";
    model = new QStandardItemModel;
    model->setHorizontalHeaderLabels(headers);
    //为view设置model
    ui->listView->setModel(model);
    ui->tableView->setModel(model);
    ui->tableView->hide();
}


2.3 修改onpushButtonclicked

model使用QStandardItem存储单个数据项

void StudentsWidget::on_pushButton_clicked()
{
    QString id   = ui->line_studentid->text();
    QString name = ui->line_name->text();
    Student student;
    student.setId(id);
    student.setName(name);
    if (studentClass.add(student))
    {
        //创建model对应的item
        QStandardItem* itemName = new QStandardItem(name);
        QStandardItem* itemStudentClass = new QStandardItem(studentClass.getName());
        QList<QStandardItem*> itemList;
        itemList << itemName << itemStudentClass;
        model->appendRow(itemList);
    }
}


2.4 现在运行程序,添加一个学生看看是什么效果吧



每当添加一个学生时,列表和表格就会同时更新显示结果,这是不是比我们直接为列表和表格添加数据便捷多了。

MVC的使用,使我们只需要关注更新model的部分,而不需要关心view该如何变化,因为当model改变了,所有关联它的view都会得到相应的更新,最令人兴奋的是你只需要维护一个model。


最后也希望大家多多支持小豆君的创作,关注小豆君的公众号“小豆君Qt分享”,最新文章都会在公众号第一时间发布,也可加入C++\Qt交流群,一起学习。

相关文章
|
3月前
|
算法 计算机视觉
基于qt的opencv实时图像处理框架FastCvLearn实战
本文介绍了一个基于Qt的OpenCV实时图像处理框架FastCvLearn,通过手撕代码的方式详细讲解了如何实现实时人脸马赛克等功能,并提供了结果展示和基础知识回顾。
145 7
|
3月前
|
文字识别 计算机视觉 开发者
基于QT的OCR和opencv融合框架FastOCRLearn实战
本文介绍了在Qt环境下结合OpenCV库构建OCR识别系统的实战方法,通过FastOCRLearn项目,读者可以学习Tesseract OCR的编译配置和在Windows平台下的实践步骤,文章提供了技术资源链接,帮助开发者理解并实现OCR技术。
177 9
基于QT的OCR和opencv融合框架FastOCRLearn实战
WK
|
1月前
|
开发框架 开发工具 C++
C++跨平台框架Qt
Qt是一个功能强大的C++跨平台应用程序开发框架,支持Windows、macOS、Linux、Android和iOS等操作系统。它提供了250多个C++类,涵盖GUI设计、数据库操作、网络编程等功能。Qt的核心特点是跨平台性、丰富的类库、信号与槽机制,以及良好的文档和社区支持。Qt Creator是其官方IDE,提供了一整套开发工具,方便创建、编译、调试和运行应用程序。Qt适用于桌面、嵌入式和移动应用开发。
WK
73 5
|
7月前
|
存储 安全 Java
Qt线程池+生产者消费者模型
Qt线程池+生产者消费者模型
314 5
|
3月前
|
计算机视觉
基于QT的opencv插件框架qtCvFrameLearn实战
这篇文章详细介绍了如何基于Qt框架开发一个名为qtCvFrameLearn的OpenCV插件,包括项目配置、插件加载、Qt与OpenCV图像转换,以及通过各个插件学习OpenCV函数的使用,如仿射变换、卡通效果、腐蚀、旋转和锐化等。
60 10
|
3月前
|
C语言 C++ Windows
QT多插件通信框架CTK编译记录
本文记录了编译QT多插件通信框架CTK的过程,包括编译结果截图、部署配置、Log4Qt编译配置、参考链接和拓展资料。文中提供了详细的编译步骤和配置文件示例,以及相关的资源链接。
QT多插件通信框架CTK编译记录
|
7月前
【qt】标准项模型1
【qt】标准项模型
43 0
|
6月前
|
编译器 C++
(10)Qt对象模型
(10)Qt对象模型
|
7月前
|
监控 数据可视化 Linux
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
|
7月前
|
索引
【qt】标准型模型 下
【qt】标准型模型 下
31 0