模型视图框架的一知半解---qt、vs

目录

一、模型视图框架

1、代码实现

2、代码思路整理

3、QStandardItemModel的增删改查

1.1 查询

1.2 添加

1.3 修改

1.4 删除


参考链接:

        Qt模型/视图框架(一) - 知乎

        Qt模型视图框架(二) - 知乎

        Qt模型视图框架(三) - 知乎

一个小白的学习历程,如有侵权请及时告知。如内容有误请大佬纠正,谢谢>.<

        原作者讲述的看起来很详细,不知道手会没会的我决定自己撸一遍代码。

        我没打算写原来那个界面数据不分离的版本。

        那么我就直接上手后面的那个MVC界面数据分离的案例了。

一、模型视图框架

1、代码实现

        首先创建了一个qt窗口界面

模型视图框架的一知半解---qt、vs_第1张图片

模型视图框架的一知半解---qt、vs_第2张图片

 目录结构如下

模型视图框架的一知半解---qt、vs_第3张图片

 添加两个类:学生信息类、班级信息类

模型视图框架的一知半解---qt、vs_第4张图片

模型视图框架的一知半解---qt、vs_第5张图片

 stuInfo.h

#pragma once

#include 

class StuInfo 
{
public:
	//get、set方法
	QString getSno() const
	{
		return sno;
	}
	void setSno(const QString &s)
	{
		sno = s;
	}

	QString getName() const
	{
		return name;
	}
	void setName(const QString &n)
	{
		name = n;
	}

private:
	QString sno;
	QString name;
};

 clsInfo.h

#pragma once

#include 
#include 

#include "StuInfo.h"

class  clsInfo
{
public:
	//get、set方法
	QString getId() const
	{
		return id;
	}
	void setId(const QString &i)
	{
		id = i;
	}

	QString getName() const
	{
		return clsName;
	}
	void setName(const QString &n)
	{
		clsName = n;
	}

	//添加学生信息
	bool addStu(const StuInfo &stuInfo)
	{
		bool flag = false;

		if (!studentMap.contains(stuInfo.getSno))//如果学号不为空
		{
			studentMap.insert(stuInfo.getSno, stuInfo.getName);//将学号和姓名存入map
			flag = true;
		}
		return flag;
	}

	//获取所有学生姓名
	QList getStuList() const
	{
		return studentMap.values();
	}

private:
	QString id;
	QString clsName;
	QMap studentMap;
};

 stuMessage.ui

模型视图框架的一知半解---qt、vs_第6张图片

 stuMessage.h

#pragma once

#include 
#include "ui_stuMessage.h"

#include "clsInfo.h"

#include  

class stuMessage : public QMainWindow
{
    Q_OBJECT

public:
    stuMessage(QWidget *parent = Q_NULLPTR);

public slots:
	void pushButtonClicked();

private:
    Ui::stuMessageClass ui;

//MVC模型视图框架
private:
	clsInfo m_classInfo;//班级信息
	QStandardItemModel *m_pModel;
};

stuMessage.cpp

#include "stuMessage.h"

stuMessage::stuMessage(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

	//给班级赋值
	m_classInfo.setId(QStringLiteral("20210101"));
	m_classInfo.setName(QStringLiteral("1班"));

	//设置model标题
	QStringList headers;
	headers << QStringLiteral("姓名") << QStringLiteral("班级") << QStringLiteral("学号");
	m_pModel = new QStandardItemModel;
	m_pModel->setHorizontalHeaderLabels(headers);

	//为界面view设置model
	ui.listView->setModel(m_pModel);
	ui.tableView->setModel(m_pModel);

	connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(pushButtonClicked()));
}

//槽函数
void stuMessage::pushButtonClicked()
{
	//给学生信息赋值
	StuInfo stuInfo;
	stuInfo.setSno(ui.lineEdit->text());
	stuInfo.setName(ui.lineEdit_2->text());

	if (m_classInfo.addStu(stuInfo))//添加学生信息
	{
		//创建model对应的Item
		QStandardItem *itemName = new QStandardItem(stuInfo.getName());
		QStandardItem *itemStuCls = new QStandardItem(m_classInfo.getName());
		QStandardItem *itemSno = new QStandardItem(stuInfo.getSno());

		//将所有的item收集起来
		QList itemList;
		itemList << itemName << itemStuCls << itemSno;
		m_pModel->appendRow(itemList);//添加到界面上
	}
}

运行结果

模型视图框架的一知半解---qt、vs_第7张图片

2、代码思路整理

        qt中MVC框架将界面与数据进行了隔离

        View-----------视图(展示数据)

        Model-----------模型(管理数据)

        Delegate-------委托(负责view和model的交互)

        view是从控件界面拖动的view控件,比如tableview、treeview、listview和自定义视图等等。

        model指的是QStandardItemModel数据模型。

        其中的view和model需要利用setModel函数绑定。

        QStandardItemModel使用QStandardItem作为数据支撑。

        QStandardItem:管理复杂的树结构件,其中每一个项目可以包含任意数据

        然后将这些item绑定到model中,再将model与view绑定。

  ----关于委托:

  参考链接:

        QT学习系列:模型/视图框架_yu1665090104的博客-CSDN博客_qt模型视图框架

        这个链接讲的还算详细吧。

        模型视图框架的一知半解---qt、vs_第8张图片

        里面解释到委托是控制用户交互方式的, 比如说要给tableview单元格中的一个数据做修改。修改数据是通过委托功能实现的。 

3、QStandardItemModel的增删改查

       QStandardItemModel是一个数据模型,基本上能满足我们的需求。

        它实现了QAbstractItemModel接口,这意味着该模型可以为任何支持接口视图提供数据。QStandardItemModel使用QStandardItem作为数据支撑。

        如果想要性能更好更灵活,可以子类化QAbstractItemModel来为不同类型的数据存储库提供支持。 例如,QDirModel为底层文件系统提供了一个模型接口

        对于数据的操作,基本上就是增删改查。接下来就开始对QStandardItemModel的增删改查方法进行介绍。因为QStandardItem是单个数据项的载体,所以我们只需要获得QStandardItem就可以获取数据并对其进行操作。

1.1 查询

1.1.1 item(int row, int clolum = 0) const

        该接口可以根据行号和列号返回QStandardItem指针。

        但是如果是一个树视图,通过这个接口只能获取顶层的item。想要获取下一分支的Item可以使用QStandardItem的child接口。

1.1.2 invisibleRootItem() const

        对于每个顶层的item,其实它都是一个不可见item的子item

        如果想遍历所有顶层item,可以使用如下方法:

QStandardItemModel *model = new QStandardItemModel;
QStandardItem *rootItem = model->invisibleRootItem();
for(int i=0; irowCount(); ++i)
{
    for(int j=0; jcolumnCount(); ++j)
    {
        QStandardItem *item = rootItem->child(i, j);
    }
}

        当然,你也可以使用QStandardItemModel::rowCount和QStandardItemModel::columnCount来遍历顶层item。

        但是如果递归遍历一棵树时,应该使用invisibleRootItem()的方法来遍历,因为这样可以给遍历树提供一个统一的方法,否则必须编写两个方法。

1.1.3 itemFromIndex(const QModelIndex &index) const

        通过QModelIndex来获取item,QModelIndex是一个用于定位item的类,是一个常用接口。

        

1.1.4 rowCount和columnCount获取行数和列数

1.1.5 data(const QModelIndex &index, int role = Qt::DisplayRole) const

        这是一个重要接口,它可以根据QModelIndex获取item中保存的数据,这对于快速检索出item所代表的数据是非常有用的。

        因为一个item可以代表很多不同类型的数据,那么我们根据role这个参数来获取该item对应的某类数据。这里role默认参数DisplayRole,即表示获取item本身显示数据

        当然,如果传递一个Qt::ToolTipRole,那么它将返回一个提示信息对应数据

        如果想获取用户自定义类型,那么可以传递一个int类型,这个类型要不小于Qt::UserRole

        data接口返回一个QVariant类型,这表明在item中可以存储QString ,int ,bool, Point等,也支持用户自定义类型,但是必须使用Q_DECLARE_METATYPE宏来向源对象进行注册声明

        与data接口相对应的是setData,用来设置数据。

即date获取数据,setData存储数据

1.1.6 findItems(const QString &text, Qt::MatchFlags flags = Qt::MatchExactly, int column = 0) const

        返回给定列使用给定标志匹配给定文本的item列表。

1.2 添加

1.2.1 appendRow(QStandardItem *item)

        添加到模型的最后一行,与其相同的有insertRow(), insertColumn()。

        该接口的另一个重载形式是appendRow(const QList &items)其参数是一个QList列表,如果所使用的视图是一个table或者tree,则该列表表示一行数据中的多列数据。

	QStandardItemModel *model1 = new QStandardItemModel;

	//添加数据
	QStringList textlist;
	textlist << "A" << "B" << "C";
	for(auto& text: textlist)
	{
		QStandardItem *item = new QStandardItem(text);
		model1->appendRow(item);
		item->setEditable(false);//设置每个Item不可编辑
	}

1.2.2 setRowCount(int), setColumnCount(int)

        设置行数,列数

    QStandardItemModel *model1 = new QStandardItemModel;
	model1->setRowCount(4);
	model1->setColumnCount(3);

1.3修改

1.3.1 setItem(int row, int column, QStandardItem *item)

        将item放置到表中

	QStandardItemModel *model1 = new QStandardItemModel;	
    QStandardItem *editIteml = new QStandardItem("G");
	model1->setItem(3, 2, editIteml);

1.3.2 set Data(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole)

        设置Index对应的item数据

1.4删除

1.4.1 clear()

        从模型中删除所有项

QStandardItemModel *model1 = new QStandardItemModel;
model1->clear();

1.4.2 removeRow()或removeColumn()

        删除行,删除列。

    //删除第1列和第4行
    QStandardItemModel *model1 = new QStandardItemModel;	
    model1->removeColumn(0);
	model1->removeRow(3);

        在删除时一定要考虑索引问题,比如说删除list某列内容为“A”的数据时你所遇到的问题,后来用foreach得到解决的那个

        上面加粗的话当然是对我自己说的,看不懂可以忽略。

        在这里为了解决索引问题,可以使用倒叙的方式,从列表最后一项开始,向前删除item。

        也可以使用findItem找出所有符合条件的item,然后删除它们。

不是特别懂

view视图

model模型

大概就是在model中绑定数据item,然后view绑定model,model再将数据item传递给view并显示出来。

确实是比我以往用widget要方便,不需要自己手动创建item然后再赋值。

但是具体有什么别的比较大的意义还不是很明白....

特别是委托,目前我感觉自己还没有用到,不知道是什么东西。

希望在以后的学习中我可以明白这些吧。

你可能感兴趣的:(VS_Qt_C++学习类,qt,开发语言,c++)