最近又开始搞QT开发了,前面学的MVC啥的都忘得差不多了,重新整理一遍思路吧。
目前的需求是:读取文本文件,表格型数据,用tableview显示出来,最后画图。这涉及到三个问题,文件读写,数据显示,数据绘图。
按照QT教材和网上分析,需要用标准项模型,标准项等实现,如果有很多项,那么循环又涉及到不断new新的标准项,感觉不妥当,又想着用二维数组吧,用法有些过时,而且插入、删除又不好整。QVector之类的也不好使。最后才发现,根本用不着setitem,只要setdata就可以了,这是最简单的方案。只需三步即可。
先来看下怎么显示数据,tableview的思路是“模型-视图”,所以要显示数据,首先得定义模型。
1 创建标准项模型Standard Item Model
// 这段可以写在头文件声明为成员变量
#include <QStandardItemModel>
QStandardItemModel *model;// 这段可以写在构造函数或回调函数里执行
model = new QStandardItemModel(this);
这就定义好了一个空模型,当然,new的时候也可以指定行列
model = new QStandardItemModel(row,col,this);
如果没指定行列,连接视图后就显示不出来。这里不指定的话,后面可以接着单独指定
model->insertRows(0,10,QModelIndex());model->insertColumns(0,5,QModelIndex());
参1是第几行(列),参2是插入几行(列)
2 用SetData插入数据
不用item,直接对模型插入数据
for(int i = 0; i<10; i++){for(int j = 0; j<5; j++){model->setData(model->index(i,j,QModelIndex()),QString::number(i+j));}}
就完成了。
下面记录一下弯路:
这里容易混淆的是,qt里有抽象项模型abstracti tem model,还有标准项模型 standard item model,我们这里用标准项模型就可以。
include了标准项模型后,就可以使用standarditemmodel 和 standarditem两种类型,分别代表模型和项。
值得注意的是,创建模型对象最好new一个指针,不然放到构造函数或者槽函数中,容易因为生命周期短,被销毁而无法在视图中显示。
3 创建标准项 Standard Item
标准项也是最好搞成指针,先创建根节点,在定义普通节点,最后将普通节点附加在根节点,模型就算是设置好了。
#include <QStandardItemModel>// 创建标准项模型QStandardItemModel *model = new QStandardItemModel(this);// 创建根项QStandardItem *parentItem = model->invisibleRootItem();// 创建普通项QStandardItem *item0 = new QStandardItem;// 设置文本item0->setText("A");// 将普通项附加到根上parentItem->appendRow(item0);
上面的代码就是创建模型的基本流程。
4 用视图来显示模型
qt常用的视图有list tree table,我们这里只看table。
直接在gui里放入tableview控件,那么将视图和模型连接起来只需要一行代码:
ui->tableView->setModel(model);
之后编译程序,就可以正常显示了:
5 槽函数中对模型进行修改
如果要在槽函数中修改模型,那么最好把模型,项之类的对象定义为main window的成员变量,这样就解决了变量传递的问题。
void MainWindow::on_action_triggered()
{QStandardItem *item = new QStandardItem;item->setText("B");parentItem->appendRow(item);
}
新建一个按钮,然后编写槽函数。在此之前,把定义在构造函数里的模型model,根节点parentItem都写在main window成员函数里,这样在槽函数就可以直接调用了。
槽函数里的思路很简单,既然模型已经定义了,就直接再追加一个item就行,之后测试,点击按钮,视图就可以更新了。
每点击一个按钮,都会在下一行追加一个item,其文本为B。
这里稍微在讲一下模型,项的原理。
其实模型就好比一个阵列式指针,里面记录了数据的位置,数据其实还是在变量里保存的,new完一个变量后,指针就指向了内存,settext其实就是往这里记录数据。然后追加到根节点后,model就好像指针一样指向了这个数据。也就是说,并不是复制数据到模型里,而是模型记录了数据的位置。
那么总结下就是,模型就是个阵列指针。数据还是保存在变量了,变量的位置由item指定。
如果删除了item,那么模型设置好的位置就没数据了,反映到视图中,就是数据没了。
这里我们在槽函数中加一句:delete item,把item指针删除,那么根节点就会追加一行,但是没有数据。
如果想删除节点,那么使用romove就可以,比如再写一个槽函数,功能是实现删除一行:
parentItem->removeRow(parentItem->rowCount()-1);
就可以删除最后一行了。这里-1是因为行从0开始。
6 循环批量插入数据
这里我们不适用根节点——节点这种定义方式,而是采用更适用于表的setItem方法来实现模型的编辑。
在引入一个按钮,定义槽函数:
void MainWindow::on_action_3_triggered()
{QStandardItem *item;for(int i = 1; i<5; i++){for(int j = 1; j<7; j++){item = new QStandardItem(QString::number(i+j));model->setItem(i-1,j-1,item);}}
}
这里首先定义一个标准项,然后循环用new创建item,然后用setitem来指定模型对应行列上的项。
这样更适用于表格数据
留一个疑问:删除节点后,item指针时循环生成时,变量怎么删除?
2 模型索引