Qt模型/视图原理(4):自定义视图(QAbstractItemView)

您所在的位置:网站首页 海康威视自定义视图 Qt模型/视图原理(4):自定义视图(QAbstractItemView)

Qt模型/视图原理(4):自定义视图(QAbstractItemView)

2024-07-03 22:05| 来源: 网络整理| 查看: 265

Qt模型/视图原理(4):自定义视图(QAbstractItemView)

本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)

本文出自本人原创著作《Qt5.10 GUI完全参考手册》网盘地址: https://pan.baidu.com/s/1iqagt4SEC8PUYx6t3ku39Q 《C++语法详解》网盘地址:https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg

若对C++语法不熟悉,建议参阅本人所著《C++语法详解》一书,电子工业出版社出版,该书语法示例短小精悍,对查阅C++知识点相当方便,并对语法原理进行了透彻、深入详细的讲解,可确保读者彻底弄懂C++的原理,彻底解惑C++,使其知其然更知其所以然。此书是一本全面了解C++不可多得的案头必备图书。

自定义视图的基本原则如下 1)、视图需要自行绘制,通常在paintEvent()函数内完成,所以除了必须实现的纯虚函数外,paintEvent()也应重新实现。另外若需要对单元格进行重新绘制、更新滚动条等,还需要重新实现resizeEvent()函数。 2)、自定义视图需要完成显示的单元格的大小和位置的计算、单元格轮廓线的绘制、滚动的计算、对单元格的选择作出处理、若有必要还需要绘制标头。 3)、另外需要记住的是视图就是一个QFrame,也就是说直接使用show()显示视图,那么视图只是一个什么也没有的窗口而已,窗口中的内容需要由程序员设计,也就是说你也可以完全不继承QAbstractItemView类,而子类化QFrame类来实现视图中内容的绘制,当然这样会失去对QAbstractItemView类中由Qt已实现的内部函数的使用。

QAbstractItemView类中的纯虚函数的原型如下 在这里插入图片描述 在这里插入图片描述

示例8.11为最小的自定义视图实现,也就是说以下代码实现的视图功能并不完善。完整的实现需要比较复杂的计算量,以下代码主要是要让读者明白,视图究竟用来做什么,做了什么。从而加深对模型/视图结构的理解。作为最小实现,本示例只处理单元格轮廓线的绘制、单元格中数据项的绘制,以及简单的选择操作 示例8.11的基本规则:使用paintEvent()函数完成由visualRect()函数返回的矩形的轮廓线及其数据项的绘制,其中数据项调用委托绘制。

示例8.11:简单的自定义视图 //m.h文件的内容 #ifndef M_H #define M_H #include class V:public QAbstractItemView{ public: //1、以下函数用于计算项目所占据的矩形(即位置和大小) QRect visualRect(const QModelIndex &index) const{ //该函数在初次运行时便会由Qt调用,调用次数依模型而定,本例3*3的表格模型, //该函数会被调用18次。参数index包含模型的索引,index会在调用时循环传递。 //比如对于本例,第一次调用时的索引为(0,0),第二次为(0,1),第3次为(0,2)... //计算项目的矩形:项目大小始终为(110,33),位置随索引而不同。 return QRect(index.column()*110,index.row()*33+20,110,33); } //2、以下函数返回鼠标光标所在位置的项目的索引 QModelIndex indexAt(const QPoint &point) const{ //该函数在点击鼠标时Qt会调用。 //参数point包含了鼠标光标的坐标位置(视图坐标) int r=(point.y()-20)/33; //计算光标位于哪一行。 int c=point.x()/110; //计算光标位于哪一列。 return model()->index(r,c); } //返回该项目的索引。 //3、以下两个函数主要用于处理对项目的选择,当选择视图中的项目时,Qt才会调用他们。 //当不需要选择项目时,以下两个函数可以不用实现。 void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) { //参数rect包含了所选项目的矩形(位置和大小,使用视图坐标) //参数flags包含了选择项目时的选择标志。 int r=(rect.y()-20)/33; //计算选中的是哪一行。 int c=rect.x()/110; //计算选中的是哪一列。 selectionModel()->select(model()->index(r,c),flags); } //选择所选中的索引。 QRegion visualRegionForSelection(const QItemSelection &s) const { //此函数用于计算所有被选择的项目占据的区域(即位置和大小)。 //参数s包含了所选择的项目的范围。 return QRegion(); } //4、以下函数用于计算视图的滚动,本例是最小实现,不需要滚动,所以不需要实现以下3个函数。 int horizontalOffset() const{ return 0; } int verticalOffset() const { return 0; } void scrollTo(const QModelIndex &index, ScrollHint hint = EnsureVisible){} //5、本示例不需要隐藏项目,所以以下函数直接返回0即可。 bool isIndexHidden(const QModelIndex &index) const{ return 0; } //6、以下函数用于处理键盘按键(比如按下左键应返回左侧的项目索引等),本示例不处理键盘按键, //所以不需要实现。 QModelIndex moveCursor(CursorAction cursorAction ,Qt::KeyboardModifiers modifiers){ return QModelIndex(); } //7、以下函数是核心,用于绘制视图的外观,也就是说若没有以下函数,则视图什么也不会显示。 void paintEvent(QPaintEvent *e){ QPainter pt(viewport()); //在视口上绘制图形 //使用QAbstractItemView::viewOptions()获取需要绘制的图形的信息(此步骤比较重要) QStyleOptionViewItem po=viewOptions(); //循环遍历模型的大小。 for(int r=0;rrowCount();r++) for(int c=0;ccolumnCount();c++){ QModelIndex i=model()->index(r,c); QRect rect=visualRect(i); //获取索引i所指项目的矩形(位置和大小) po.rect=visualRect(i); //处理项目被选择的情形 if(selectionModel()->isSelected(i)){ po.state |= QStyle::State_Selected;} //使用代理绘制数据项(即项目),这里也可使用自定义的代理(若已添加) itemDelegate()->paint(&pt,po,i); //以下代码用于绘制视图单元格的轮廓线。 pt.save(); pt.setPen(QPen(QColor(111,1,1))); //创建画笔。 pt.drawLine(rect.bottomLeft(),rect.bottomRight()); pt.drawLine(rect.bottomRight(),rect.topRight()); pt.restore(); } //for结束 } //paintEvent结束 }; class B:public QWidget{ Q_OBJECT public: QStandardItemModel *d; V *pv; B(QWidget *p=0):QWidget(p){ d=new QStandardItemModel(3,3); V* pv=new V; //使用自定义的视图 //向模型中添加数据 d->setData(d->index(0,0),"AAA"); d->setData(d->index(0,1),"BBB"); d->setData(d->index(1,0),"CCC"); d->setData(d->index(1,2),"DDD"); d->setData(d->index(1,1),"EEE"); d->setData(d->index(2,0),"FFF"); d->setData(d->index(1,1),QIcon("F:/1i.png"),Qt::DecorationRole); //向视图中添加标签,以用于视图的标头,以下代码主要演示视图还可以像使用一个QFrame那样使用。 QLabel *pp=new QLabel("111",pv); pp->setAutoFillBackground(1); //使标签不透明。 pp->setAlignment(Qt::AlignCenter); pp->resize(111,20); QLabel *pp1=new QLabel("222",pv); pp1->setAutoFillBackground(1); pp1->setAlignment(Qt::AlignCenter); pp1->resize(111,20); pp1->move(111,0); QLabel *pp2=new QLabel("333",pv); pp2->setAutoFillBackground(1); pp2->setAlignment(Qt::AlignCenter); pp2->resize(111,20); pp2->move(222,0); //pv->setItemDelegate(pt); //也可以添加自定义代理,以使用自定义代理绘制数据项。 pv->setModel(d); pv->resize(333,222); pv->show(); } }; #endif // M_H //m.cpp文件内容 #include "m.h" int main(int argc, char *argv[]){ QApplication app(argc,argv); B w; return app.exec(); }

运行结果及说明见图8-37 在这里插入图片描述

本文作者:黄邦勇帅(原名:黄勇)

在这里插入图片描述



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3