在设计窗口的控件栏有一种控件叫Item Views,非常有用但是很多人不会,这里详细讲一下.
用处:
按照一定格式现实数据(列表,表格,树),并且可以在对数据操作的时候增加槽函数.
Excel:
还有这种文件树状图:
基本原理:
就是MVC(Model View Controller,模型-视图-控制器/代理):
这个在游戏和网络应用开发都涉及到:
http://c.biancheng.net/view/1864.html
https://zhuanlan.zhihu.com/p/42719287
都讲得不错,其实就是一种解耦的思想.
现在我们知道模型和视图关联,不同的模型要关联不同的视图.
先放一张模型类和视图类的大图:
下面本文主要分三个部分,依次讲解图中三种model/view的配合使用:
1.QStringListModel和QListView的配合使用:
它们的详细用法分为以下几个部分:
1.1.初始化(在父窗口的构造函数中演示):
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//QStringListModel可以理解为一个储存着数据的盒子,要先准备好盒子里的初始数据
QStringList theStrList; //保存初始 StringList
theStrList<<"北京"<<"上海"<<"天津"<<"河北"<<"山东"<<"四川"<<"重庆"<<"广东"<<"河南"; //初始化 StringList
//创建模型对象,注意它的构造函数的参数是父窗口,而不是列表视图控件
theModel=new QStringListModel(this);
//setStringList() 函数可以初始化数据模型的字符串列表的内容
//也就是把数据装进这个盒子里
theModel->setStringList(theStrList);
//在这里使用setModel()关联模型和视图
//为listView设置数据模型
ui->listView->setModel(theModel);
}
1.2.编辑设置:
设置 QListView 的条目是否可以编辑,以及如何进入编辑状态
QListView::setEditTriggers():设置 QListView 的条目是否可以编辑,以及如何进入编辑状态
参数如下(从帮助手册截下来的):
1.3.添加和修改操作:
在列表中添加一行,或者修改某一行的数据
首先要在知道:
模型索引(model index)
模型不提供接口直接给你数据,而是要先获取模型索引对象,
再用模型索引从模型中获取数据.(这个东西看起来多此一举,麻烦了,但在树状视图中就简单了)
具体讲解还是看:http://c.biancheng.net/view/1864.html
讲的非常基础了
同时还要知道
的几个接口:
bool QStringListModel::insertRow (int row):row 是一个行号,表示在 row 行之前插入一个空行,这个行没有内容;
QModelIndex
QStringListModel::index(int row, int column = 0, const
QModelIndex
&parent = QModelIndex()):根据传递的行号、列号、父项的模型索引生成一个模型索引,这个模型索引就是你在模型中获取,修改数据的凭证;intint QModelIndex::row():返回本模型索引对象的列数;
QModelIndex QListView::currentIndex():返回视图中选中的项的模型索引,很方便;
int QStringListModel::rowCount ():当前模型的总行数;
(这里再说一点,模型中的每个项会有很多role–角色,在不同的条件下显示不同的role,就好像一个人有很多身份,如父亲,职员,丈夫,在不同的场合有不同的身份)
bool QStringListModel::setData(const
QModelIndex
&index, const
QVariant
&value, int role = Qt::EditRole):将index处的项的指定role的数据设为value;
一个项的角色(role)的可选参数如下(也是从帮助手册当的):
结论:
在添加项(行)的步骤:
用insertRow()添加一行准备放数据—->使用index()获取目标项的模型索引—->通过setData()设置项的数据;
修改项(行的步骤):
使用index()获取目标项的模型索引—->通过setData()设置项的数据;
实例代码:
//在列表的最后添加一行
//添加一个空行做准备
theModel->insertRow(theModel->rowCount());
//获取最后一行的模型索引
QModelIndex index=theModel->index(theModel->rowCount()-1);
//根据模型索引修改最后一项的显示角色的数据
theModel->setData(index,"添加的新数据",Qt::DisplayRole);
1.4.删除操作:
删除一行和删除多行,两个QStringListModel提供的接口;
removeRow(int row):删除指定行;
removeRows(int row,int count):从row行开始,删除count列;
1.5:查询操作:
也就是在代码中获取指定位置的项的值
主要就是这个方法:
Q
StringList QStringListModel::stringList() const:就是把模型中的数据取出来
然后你再对获取到的QStringList指定位置查询就好.
2.QStandardItemModel和QTableView的配合使用:
有了上面的操作经验,这个也很简单了,但还是有几点区别说明一下:
1.模型类和视图类都变了,注意一下;
2.在表格中还涉及到了表头
3.在选择的时候,可以一次选中多个单元格,为了知道获取的单元格,就又多了个类QItemSelectionModel用来获取选中单元格的模型索引;
4.比列表方便的是,表格添加行的时候不用先创建空白行了
5.其他的思想,套路大同小异,聪明的你们一定看帮助文档就能搞定
基本操作代码演示:
说明:在主窗口中建立QTableView控件,下面的代码是主窗口的构造函数代码,在其中进行了一些基本操作(建议复制放到Qt里面看):
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
//这个就是数据模型
QStandardItemModel* themodel;
//这个是方便获得模型索引的类对象,由数据模型构造(在后面)
QItemSelectionModel*theselection;
//这里创建一个五行七列的表格
themodel=new QStandardItemModel(5,7,this);
//根据数据模型创建选择模型
theselection=new QItemSelectionModel(themodel);
//关联数据模型和视图模型
ui->tableView->setModel(themodel);
//关联视图模型和选择模型
ui->tableView->setSelectionModel(theselection);
//设置选择模式,具体参数及含义看帮助文档吧
ui->tableView->setSelectionMode(QAbstractItemView::ExtendedSelection);
ui->tableView->setSelectionBehavior(QAbstractItemView::SelectItems);
//下面依次进行一些基本操作:
//1.首先是初始化表格内容:
QStandardItem*item;
for(int i=0;i<themodel->columnCount();i++){
for(int j=0;j<themodel->rowCount();j++){
item=new QStandardItem(QString::number((i+1)*(j+1)));//这里注意一下,QStandard构造时参数要求是QString
item->setCheckable(true);//这个函数可以给每个小格加个勾选框
//底下这个是核心方法.
themodel->setItem(j,i,item);
/*void QStandardItemModel::setItem(int row, int column, QStandardItem *item)
不用索引模型,直接修改,方便不少*/
}
}
//2.设置表格表头,水平反向和竖直反向的都要有:
QStringList horizontalHeader= QStringList();
horizontalHeader<<"周一"<<"周二"<<"周三"<<"周四"<<"周五"<<"周六"<<"周日";
//底下这个是核心方法
themodel->setHorizontalHeaderLabels(horizontalHeader);
/*void QTableView::setVerticalHeader(QHeaderView *header)
这个设置表头的是view而不是model,
显然,表头的数据不归数据模型管,
所以表头不算在列数和行数内*/
//竖直表头同理
QStringList vertical=QStringList();
vertical<<"no.1"<<"no.2"<<"no.3"<<"no.4"<<"no.5";
themodel->setVerticalHeaderLabels(vertical);
//3.添加一行
QList<QStandardItem*> newrow;
for(int i=0;i<themodel->columnCount();i++){
newrow<<new QStandardItem("0");
}
//底下这个是核心方法
themodel->insertRow(themodel->rowCount(),newrow);
//删除同理.方法是:QList<QStandardItem *> QStandardItemModel::takeRow(int row)
//4.获取选中的单元格并操作
//获取选择单元格的模型索引列表
QModelIndexList selectedIndex=theselection->selectedIndexes();
for (int i=0;i<selectedIndex.count();i++)
{ //获取一个模型索引
QModelIndex aIndex=selectedIndex.at(i);
//获取项数据
QStandardItem* aItem=themodel->itemFromIndex(aIndex);
//然后就可以对项数据进行操作了
}
//5.查看某处的单元格的勾选框选中情况
QStandardItem* aItem=themodel->item(1,2); //最后一列是逻辑型
if (aItem->checkState()==Qt::Checked){
//这里就是对勾选中的单元格进行的操作
}
}
待改进:更改table的显示样式,更好看一些,能表头独立颜色,单元格颜色交错开那种,还有右键菜单,菜单这个可以看这个博客
https://blog.csdn.net/weixin_33912445/article/details/91743835?utm_medium=distribute.pc_relevant.none-task-blog-baidujs-8
;
3.QStandardItemModel和QTreeView的配合使用:
https://blog.csdn.net/dpsying/article/details/80383752
这个博客讲的很不错了,等我再了解了解;