开发者社区> 科技小能手> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Qt学习之路(42): QStringListModel

简介:
+关注继续查看
今天开始我们要看看Qt的model-view类了。正如前面说的那样,之前三节的item class类只是Qt为了方便我们使用而封装了的一些操作。比起真正的model-view类来,那些类更易于使用,但是功能也会更简单,并且缺少实时性的支持,比如我们并不方便实现插入、删除等一些常见操作。而现在我们要说的model-view类使用起来可能会复杂一些,但是功能强大,并且在model更新时会自动更新view,而model多是一些数据集合,因此比较便于操作。
 
model-view类中,view大致有三种:list、tree和table,但是model千奇百怪,不同的业务,甚至同样的业务不同的建模都会有不同的model。为了方便使用,Qt提供了一些预定义好的model供我们使用。QStringListModel是其中最简单的一种。
 
顾名思义,QStringListModel就是封装了QStringList的model。QStringList是一种很常用的数据类型,它实际上是一个字符串列表。我们可以想象,对于一个list来说,如果提供一个字符串列表形式的数据,就应该能够把这个数据展示出来。因为二者是一致的:QStringList是线性的,而list也是线性的。所以,QStringListModel很多时候都会作为QListView的model。
 
下面我们来看怎么使用它们。比起前面的QListWidget,这里要使用两个类:QStringListModel和QListView,并且还有一些辅助类。不过你可以看到,即便这样复杂的工作,我们的代码也不会很多的:
 
mylistview.h
#ifndef MYLISTVIEW_H 
#define MYLISTVIEW_H 
 
#include <QtGui> 
 
class MyListView : public QWidget 

        Q_OBJECT 
public
        MyListView(); 
 
private
        QStringListModel *model; 
        QListView *listView; 
 
private slots: 
        void insertData(); 
        void deleteData(); 
        void showData(); 
}; 
 
#endif // MYLISTVIEW_H
 
mylistview.cpp
#include "mylistview.h" 
 
MyListView::MyListView() 

        model = new QStringListModel(this); 
        QStringList data; 
        data << "Letter A" << "Letter B" << "Letter C"
        model->setStringList(data); 
        listView = new QListView(this); 
        listView->setModel(model); 
        QHBoxLayout *btnLayout = new QHBoxLayout; 
        QPushButton *insertBtn = new QPushButton(tr("insert"), this); 
        QPushButton *delBtn = new QPushButton(tr("Delete"), this); 
        QPushButton *showBtn = new QPushButton(tr("Show"), this); 
        btnLayout->addWidget(insertBtn); 
        btnLayout->addWidget(delBtn); 
        btnLayout->addWidget(showBtn); 
        QVBoxLayout *mainLayout = new QVBoxLayout(this); 
        mainLayout->addWidget(listView); 
        mainLayout->addLayout(btnLayout); 
        this->setLayout(mainLayout); 
 
        connect(insertBtn, SIGNAL(clicked()), this, SLOT(insertData())); 
        connect(delBtn, SIGNAL(clicked()), this, SLOT(deleteData())); 
        connect(showBtn, SIGNAL(clicked()), this, SLOT(showData())); 

 
void MyListView::insertData() 

        bool isOK; 
        QString text = QInputDialog::getText(NULL, "Insert""Please input new data:"
                                                                                 QLineEdit::Normal, "You are inserting new data.", &isOK); 
        if(isOK) { 
                int row = listView->currentIndex().row(); 
                model->insertRows(row, 1); 
                QModelIndex index = model->index(row); 
                model->setData(index, text); 
                listView->setCurrentIndex(index); 
                listView->edit(index); 
        } 

 
void MyListView::deleteData() 

        if(model->rowCount() > 1) { 
                model->removeRows(listView->currentIndex().row(), 1); 
        } 

 
void MyListView::showData() 

        QStringList data = model->stringList(); 
        QString str; 
        foreach(QString s, data) { 
                str += s + "\n"
        } 
 
        QMessageBox::information(this"Data", str); 

 
 
来看看我们的代码吧。
 
首先我们创建一个QStringListModel的对象。然后创建一个QStringList对象,并且把这个对象设置为model的数据。此时,这个model已经拥有数据了。然后,我们创建一个QListView的对象,并把model设置为它的model。后面是三个按钮的创建以及信号槽的连接,这里就不再赘述。
 
先来运行一下看看结果吧!
 
我们只是把QStringListModel设置为QListView的model,QListView就已经可以把model里面的数据展示出来了。下面我们看看增、删、改的操作。
 
先来看增加数据的操作。这部分是在代码中的insertData()函数实现的。先把那个函数拿出来看看:
 
void MyListView::insertData() 

        bool isOK; 
        QString text = QInputDialog::getText(NULL, "Insert""Please input new data:"
                                                                                 QLineEdit::Normal, "You are inserting new data.", &isOK); 
        if(isOK) { 
                int row = listView->currentIndex().row(); 
                model->insertRows(row, 1); 
                QModelIndex index = model->index(row); 
                model->setData(index, text); 
                listView->setCurrentIndex(index); 
                listView->edit(index); 
        } 
}
 
我们使用QInputDialog::getText()函数要求用户输入数据。这部分在前面讲过,这里也不再赘述。如果用户点击了OK按钮,首先,我们使用listView()->currentIndex()函数,获取QListView当前行。注意,这个函数的返回值是一个QModelIndex类型。这个类我们以后再说,只要知道这个类保存了三个重要的数据:行、列以及属于哪一个model。我们调用其row()函数获得行,这个返回值是一个int,也就是第几行。然后model插入一行。insertRows()函数签名如下:
 
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex());
 
这个函数原本是QAbstractListModel类的函数,而QStringListModel把它覆盖了。所以我们会发现它还需要另外的一个参数。我们调用 insertRows(row, 1); ,所谓1就是指插入1条数据,而前面又把row保存成当前行,因此,这行语句实际上是在当前的 row 行插入 count 行,这里的 count = 1。然后我们使用model的index()函数获取当前行的QModelIndex对象,使用setData()函数把我们用QInputDialog接受的数据插入。这里其实是一个冗余的操作,因为用currentIndex()函数已经获取当前行了。这么写仅仅是为了展示如何使用这个函数。不过,你知道了insertRow()函数,就可以很容易的做出插入空白行的效果了。然后我们把当前行设为新插入的一行,并调用edit()函数,这个函数使得这一行可以被编辑。就这样,我们向model插入了数据。
 
然后来看删除数据的操作:
 
void MyListView::deleteData() 

        if(model->rowCount() > 1) { 
                model->removeRows(listView->currentIndex().row(), 1); 
        } 
}
 
使用model的removeRows()函数可以轻松的完成这个功能。这个函数同前面所说的insertRows()很类似,就不再多说了。需要注意的是,我们用rowCount()函数判断了一下,要求最终始终保留1行。这是因为如果你把数据全部删除,你就不能再插入数据了,因为那时侯按照我们所写的插入逻辑就不对了。所以,前面所说的插入操作实际上还需要再详细考虑。
 
最后那个showData()仅仅为了查看model的数据,没有什么要说的东西。你可以在insert或者remove完成后查看一下model里面的数据是不是真的被修改了。
 
关于QStringListModel就说这么多。你可以看到,我们的几乎所有操作都是针对model的,也就是说,我们直接针对的是数据,而model侦测到数据发生了变化,会立刻通知view刷新。这样,我们就可以把精力集中到对数据的操作上,而不用担心view的同步等操作。这也是model-view模型的一个便捷之处。

本文转自 FinderCheng 51CTO博客,原文链接:
http://blog.51cto.com/devbean/265057

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
经典论文系列 | 重新思考在ImageNet上的预训练
这是一篇19年何凯明发的论文,论文基于目标检测、实例分割和人体关键点检测三个方向进行了多项实验,比较了从零使用随机初始化开始训练与使用预训练进行fine-tuning的效果,并得出了一些结论。 在本文将介绍论文的主要思想,主要结论,一些细节和作者基于实验结论上的讨论。
182 0
Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效
原文:Silverlight & Blend动画设计系列六:动画技巧(Animation Techniques)之对象与路径转化、波感特效   当我们在进行Silverlight & Blend进行动画设计的过程中,可能需要设计出很多效果不一的图形图像出来作为动画的基本组成元素。
912 0
将Xml字符串转换成(DataTable || DataSet || XML)对象
/// /// 把DataSet、DataTable、DataView格式转换成XML字符串、XML文件 /// ////// public class DataToXml { /**//// /// 将DataT...
813 0
091101 T IModel
大致思想参见《20090522》。今天和陈伟强聊了一晚上的ORM的问题,说了一下我想要的ORM是什么样的。然后最后的收获是:目前的ORM框架已经十分的高功能,所以想要在这上面达到“任意”映射的功能,只要在partial类中加入新的属性和方法(添加),然后再为模型定义一个接口(减少),就行了。
580 0
23703
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载