简介
Qt的Model-View框架是MVC设计模式的变形,主要是由Model和View组成,Model中包含数据,View负责将数据以某种方式呈现出来,如表格,树形以及列表形式。那么MVC设计模式中的Controller并非舍弃而是将Controller中一部分的功能添加到了View中,另一部分则是由Delegate完成,完整的Qt Model-View框架是由Model-View-Delegate构成。
Model-ViewFramework
Model与Data
在Model-View中数据Data存放在Item之中,Model包裹着Item,数据的组织形式可以是多总多样的,这要视具体的项目而定。通过查阅Qt文档,可以很容易的将Item放入Model中,而获取Item中的数据不是直接通过Model而是通过QModelIndex,可以在View,Delegate和seletionModel获取QModelIndex,QModelIndex不仅可以获得Item中的数据,而且可以获得包含该Item的Model,也就是说,QModelIndex是Item和Model的桥梁。
Model-QModelIndex-Item
选择与简单编辑
在PC客户端用户选择表中的数据,可以有多种选择方式,单选、多选、按住Shift或Ctrl键进行多选等,而选择是交由View完成的,通过设置View的selectionBehavior与selectionMode属性可以设定选择方式。
1. SelectionBehavior
QAbstractItemView::SelectItems 只能选择一个Item
QAbstractItemView::SelectRows 按整行进行选择
QAbstractItemView::SelectColumns 按整列进行选择
2. SelectionMode
QAbstractItemView::SingleSelection :只能选择单个Item,单个行或列
QAbstractItemView::ContiguousSelection :可以进行多选,但选择的元素,行或列必须连成一个整体,中间不可以有漏选。
QAbstractItemView::ExtendedSelection :可以进行多选,选择的元素之间可以有不被选择的元素,在选择的同时必须按住shift或者ctrl键。
QAbstractItemView::MultiSelection :同ContiguousSelection,只是不需要按住Shift或者Ctrl选择。
QAbstractItemView::NoSelection :Items不可以被选择。
通过Item设置setEditable(bool editable)可以设置Item是否可以进行修改,true表示可以修改,反之不可以修改。
自定义View
有两种方法可以自定义View,一种方法是新建一个继承于QAbstractItemDelegate的类,另一种方法是新建一个继承与QAbstractItemView的类。
表1到表2
表1与表2的区别是表二第二列使用了类似于进度条的形式展现数据。
在这里我选择使用新建一个继承于QAbstractItemDelegate的类BarDelegate,以下是该类的声明。
classBarDelegate:publicQAbstractItemDelegate
{
public:
BarDelegate(QObject*parent=0);
voidpaint(QPainter*painter,
constQStyleOptionViewItem&option,
constQModelIndex&index)const;
QSizesizeHint(constQStyleOptionViewItem&option,
constQModelIndex&index)const;
};
sizeHint
该函数必须与paint函数一同实现,真正的大小是可以改变的,这里只是给一个不会超过尺寸限制的QSize并且也能够将Item包裹进去。
paint
该函数需要实现的功能就是绘图,这里绘制的矩形框的大小,是由option和index共同给定的,一方面,option给定当前包裹item矩形的大小,以及用户对View中Item的操作情况,也就是option.state,通过index的data()函数可以十分方便的获得Item中的数据,并将数据(这里是100以内的随机数)转换成矩形的长度。
关键代码如下:
voidBarDelegate::paint(QPainter*painter,constQStyleOptionViewItem&option,constQModelIndex&index)const
{
if(option.state&QStyle::State_Selected)
{
painter->fillRect(option.rect,option.palette.highlight());
}
intvalue=index.data(Qt::DisplayRole).toInt();
doublefactor=(double)value/100.0;
painter->save();
if(factor>1)
{
painter->setBrush(Qt::red);
factor=1;
}
else
{
painter->setBrush(QColor(0,(int)(factor*255),255-(int)(factor*255)));
}
painter->setPen(Qt::black);
painter->drawRect(option.rect.x()+2,option.rect.y()+2,
(int)(factor*(option.rect.width()-5)),
option.rect.height()-5);
painter->restore();
}