目录
一、模型视图框架
1、代码实现
2、代码思路整理
3、QStandardItemModel的增删改查
1.1 查询
1.2 添加
1.3 修改
1.4 删除
参考链接:
Qt模型/视图框架(一) - 知乎
Qt模型视图框架(二) - 知乎
Qt模型视图框架(三) - 知乎
一个小白的学习历程,如有侵权请及时告知。如内容有误请大佬纠正,谢谢>.<
原作者讲述的看起来很详细,不知道手会没会的我决定自己撸一遍代码。
我没打算写原来那个界面数据不分离的版本。
那么我就直接上手后面的那个MVC界面数据分离的案例了。
首先创建了一个qt窗口界面
目录结构如下
添加两个类:学生信息类、班级信息类
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
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中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模型视图框架
这个链接讲的还算详细吧。
里面解释到委托是控制用户交互方式的, 比如说要给tableview单元格中的一个数据做修改。修改数据是通过委托功能实现的。
QStandardItemModel是一个数据模型,基本上能满足我们的需求。
它实现了QAbstractItemModel接口,这意味着该模型可以为任何支持该接口的视图中提供数据。QStandardItemModel使用QStandardItem作为数据支撑。
如果想要性能更好更灵活,可以子类化QAbstractItemModel来为不同类型的数据存储库提供支持。 例如,QDirModel为底层文件系统提供了一个模型接口
对于数据的操作,基本上就是增删改查。接下来就开始对QStandardItemModel的增删改查方法进行介绍。因为QStandardItem是单个数据项的载体,所以我们只需要获得QStandardItem就可以获取数据并对其进行操作。
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 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 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 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然后再赋值。
但是具体有什么别的比较大的意义还不是很明白....
特别是委托,目前我感觉自己还没有用到,不知道是什么东西。
希望在以后的学习中我可以明白这些吧。