Qt学习之路——Model/View

August 9th, 2013 by JasonLe's Tech Leave a reply »

今天终于开始学习Qt GUI库的精华,也就是model/view,这个模型利用了MVC的思想,在不改变底层数据结构的基础上,可以定义不同view的的展示形式,比如list combobox tree …………

MVC相信大家都很熟悉了,本文不再赘述。

这个是MVC的基本结构,model/view 相关类可以被分成上面所提到的三组:models,views,delegates。

从model发出的信号通知view数据源中的数据发生了改变。
从view发出的信号提供了有关被显示的数据项与用户交互的信息。
从delegate发生的信号被用于在编辑时通知model和view关于当前编辑器的状态信息。

Models

所有的item models都基于QAbstractItemModel类,这个类定义了用于views和delegates访问数据的接口。
数据本身不必存储在model,数据可被置于一个数据结构或另外的类,文件,数据库,或别的程序组件中。
关于model的基本概念在Model Classes部分中描述。
QAbstractItemModel提供给数据一个接口,它非常灵活,基本满足views的需要,无论数据用以下任何样的形式
表现,如tables,lists,trees。然而,当你重新实现一个model时,如果它基于table或list形式的数据结构,最好从QAbstractListModel,QAbstractTableModel开始做起,因为它们提供了适当的常规功能的缺省实现。这些类可以被子类化以支持特殊的定制需求。子类化model的过程在Create New Model部分讨论
QT提供了一些现成的models用于处理数据项:
QStringListModel 用于存储简单的QString列表。
QStandardItemModel 管理复杂的树型结构数据项,每项都可以包含任意数据。
QDirModel 提供本地文件系统中的文件与目录信息。
QSqlQueryModel, QSqlTableModel,QSqlRelationTableModel用来访问数据库。
假如这些标准Model不满足你的需要,你应该子类化QAbstractItemModel,QAbstractListModel或是
QAbstractTableModel来定制。

Views

不同的view都完整实现了各自的功能:QListView把数据显示为一个列表,QTableView把Model 中的数据以table的形式表现,QTreeView 用具有层次结构的列表来显示model中的数据。这些类都基于QAbstractItemView抽象基类,尽管这些类都是现成的,完整的进行了实现,但它们都可以用于子类化以便满足定制需求。

Delegates


QAbstractItemDelegate 是model/view架构中的用于delegate的抽象基类。缺省的delegate实现在QItemDelegate类中提供。它可以用于Qt标准views的缺省 delegate.

对于排序,在model/view架构中,有两种方法进行排序,选择哪种方法依赖于你的底层Model。
假如你的model是可排序的,也就是它重新实现了QAbstractItemModel::sort()函数,QTableView与QTreeView都提供了API,允许你以编程的方式对Model数据进行排序。

参考:http://qt-project.org/doc/qt-4.8/modelview.html
然后我编了一个listiew与combobox结合的程序。实现了数据和视图的分离,我在大二的时候,刚开始学习GUI编程,视图和数据的结合是写死的。导致当加入一个新的funciton的时候,界面会乱套,所以这个分离是十分必要的。

首先我选了一个比较简单的listview 首先线创造一个QStringListModel,然后将QStringList类型导入到这个model,最后将这个model放到view中,玩成初始化。Model indexes为views与delegages提供model中数据项定位的信息,它与底层的数据结构无关。
由于model与view是分离的,导致要对model操作时,必须获取该item的index,使用ui->listView->currentIndex().row();获取row,然后插入到model中

MainWindow::MainWindow(QWidget *parent) :
 QMainWindow(parent),
 ui(new Ui::MainWindow)
{
 ui->setupUi(this);

 QStringList list;
 list <<"Lee" <<"Zhang"<<"Wang"; model = new QStringListModel(this); model->setStringList(list);

 ui->listView->setModel(model);
 ui->comboBox->setModel(model);

 ui->listView->setEditTriggers(QAbstractItemView::AnyKeyPressed | QAbstractItemView::DoubleClicked);
}
void MainWindow::on_pushButton_3_clicked()
{
 //add
 int row = model->rowCount();//获取多少行

 model->insertRows(row,1);//因为和数组一样是从0开始的,所以等于在新的一行插入。

 QModelIndex index = model->index(row);//按照row创建新的index
 ui->listView->setCurrentIndex(index);
 ui->listView->edit(index);
}
void MainWindow::on_pushButton_2_clicked()
{
 //insert
 int row = ui->listView->currentIndex().row();//获取目前选中的index所处row

 model->insertRows(row,1);

 QModelIndex index = model->index(row);
 ui->listView->setCurrentIndex(index);
 ui->listView->edit(index);
}

void MainWindow::on_pushButton_clicked()
{
 //delete
 model->removeRows(ui->listView->currentIndex().row(),1);
}