QT项视图类主要有三种: QListView,QTreeView,QTableView,对应的基础Model为 QAbstractItemModel(QStandardItemModelo为QAbstractItemModel实现), 对于QListView和QTableView则分别提供了QStringListModel,QAbstractTableModel实现. 

   一直不太喜欢用MVC模型,对于很简单的视图,使用MVC反而显得有点复杂,大材小用了. QT中对于QListView,QTreeView,QTableView这三个视图提供了其简便实现类QListWidget,QTreeWidget,QTableWidget. 如果处理比较复杂且数据量比较大的视图,MVC就显现出其优越性了,下面看例子:

 

   

QT MVC模型_数据

 

一. QTableWidget实现

QTableWidget tableWidget;
tableWidget.setAlternatingRowColors(true);
tableWidget.setWindowTitle("历史曲线");

// 设置水平/垂直方向标签
tableWidget.setColumnCount(2);
tableWidget.setRowCount(2);
tableWidget.setHorizontalHeaderLabels(QStringList()<<"0分钟"<<"5分钟");
tableWidget.setVerticalHeaderLabels(QStringList()<<"0小时"<<"1小时");

// 填充数据
for(int i=0;i<2;i++) // 行
{
for(int j=0;j<2;j++) // 列
{
QTableWidgetItem *item=new QTableWidgetItem;
item->setText(QString::number(datas[i*2+j]));

tableWidget.setItem(i,j,item);
}
}

tableWidget.show();

   QTableWidget构建表格,需要手动一个一个添加数据,视图与数据层深度耦合

 

二. QListView+QStandardItemModel实现

// 标准model实现
QStandardItemModel hisModel(2,2); // 定义2行2列模型
hisModel.setHorizontalHeaderLabels(QStringList()<<"0分钟"<<"5分钟");
hisModel.setVerticalHeaderLabels(QStringList()<<"0小时"<<"1小时");
for(int i=0;i<2;i++) // 行
{
for(int j=0;j<2;j++) // 列
{
QStandardItem *item=new QStandardItem;
item->setText(QString::number(datas[i*2+j]));

hisModel.setItem(i,j,item); // model设置数据
}
}

QTableView tableView;
tableView.setModel(&hisModel); // 只需要设置model就行了,将数据渲染工作交给model
tableView.setAlternatingRowColors(true);
tableView.setWindowTitle("历史曲线");
tableView.show();

   将数据渲染逻辑交给model, view层只需调用setModel()即可显示数据,

 

三.  QListView+QAbstractTableModel实现

       对于上述代码,当数据修改后,不能即时在view上显现出来,代码比较固化. 下面通过实现QAbstractTableModel来实现:

QT MVC模型_List_02

   

 

main.cpp

int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTextCodec::setCodecForCStrings(QTextCodec::codecForName("GBK"));
QTextCodec::setCodecForTr(QTextCodec::codecForName("GBK"));

QList<double> datas;
datas<<89.2<<98.3<<45.8<<65.9;

HistoryModel hisModel;
hisModel.setHisDatas(datas); // 当数据改变后,只需要重新调用setHisDatas()就可以更改视图

QTableView tableView;
tableView.setModel(&hisModel);
tableView.setAlternatingRowColors(true);
tableView.setWindowTitle("历史曲线");
tableView.show();

return app.exec();
}

historymodel.h

/**
* 派生QAbstractTableModel
*/
class HistoryModel:public QAbstractTableModel
{
Q_OBJECT

public:
HistoryModel(QObject *parent=0);
~HistoryModel();

// 重载,返回行数目
int rowCount(const QModelIndex &parent) const;
// 重载,返回列数目
int columnCount(const QModelIndex &parent) const;
// 重载,设置每一单元格数据
QVariant data(const QModelIndex &index, int role) const;
// 重载,设置表头数据
QVariant headerData(int section, Qt::Orientation orientation,int role) const;
// 重载,设置单元格属性
Qt::ItemFlags flags(const QModelIndex &index) const;

// 设置模型数据源
void setHisDatas(const QList<double> hisdatas);

private:
QStringList horizontalList;
QStringList verticalList;
QList<double> hisdatas;
};

 

historymodel.cpp

#include "historymodel.h"

HistoryModel::HistoryModel(QObject *parent):QAbstractTableModel(parent)
{
horizontalList<<"0分钟"<<"5分钟";
verticalList<<"0小时"<<"1小时";
}

HistoryModel::~HistoryModel()
{

}

void HistoryModel::setHisDatas(const QList<double> hisdatas)
{
this->hisdatas=hisdatas;

// 调用reset()告诉任何一个使用这个模型的视图,它们所有的数据都无效了,这样就会强制它们为可见的项刷新数据
reset();
}

int HistoryModel::rowCount(const QModelIndex &parent) const
{
return verticalList.size();
}


int HistoryModel::columnCount(const QModelIndex &parent) const
{
return horizontalList.size();
}

QVariant HistoryModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if(role==Qt::DisplayRole)
{
if(orientation==Qt::Horizontal) // 水平表头
{
return horizontalList[section];
}

return verticalList[section]; // 垂直表头
}

return QVariant();
}

Qt::ItemFlags HistoryModel::flags(const QModelIndex &index) const
{
Qt::ItemFlags flag=QAbstractItemModel::flags(index);

// flag|=Qt::ItemIsEditable // 设置单元格可编辑,此处注释,单元格无法被编辑
return flag;
}

QVariant HistoryModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();

if(role==Qt::TextAlignmentRole)
{
return int(Qt::AlignHCenter|Qt::AlignVCenter); // 设置单元格对齐方式
}else if(role==Qt::DisplayRole)
{
int offset=index.row()*horizontalList.size()+index.column(); // 设置单元格数据
return hisdatas[offset];
}

return QVariant();
}

   通过子类化QAbstractTableModel,重新实现模型内虚方法,设置项的显示方式,项数据. 

 

设置第一个表头数据,见下面效果:

 

QT MVC模型_MVC_03