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交流群,一起学习。

相关文章
|
2月前
|
开发框架 网络协议 数据库
Qt:构建跨平台应用的强大框架
Qt:构建跨平台应用的强大框架
|
2月前
|
存储 安全 Java
Qt线程池+生产者消费者模型
Qt线程池+生产者消费者模型
71 5
|
2月前
【qt】标准项模型1
【qt】标准项模型
21 0
|
1月前
|
编译器 C++
(10)Qt对象模型
(10)Qt对象模型
|
2月前
|
监控 数据可视化 Linux
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
Qt Model&View&Delegate(模型-视图-代理) 介绍和使用
|
2月前
|
数据库 开发者 Windows
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解-2
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解
|
2月前
|
XML 设计模式 JSON
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解-1
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解
|
2月前
|
索引
【qt】标准型模型 下
【qt】标准型模型 下
9 0
|
2月前
【qt】标准项模型2
【qt】标准项模型
9 0
|
2月前
|
索引
【qt】初识模型和视图2
【qt】初识模型和视图
12 0