天天看点

QAbstractItemModel 与 QItemDelegate关系

QAbstractListModel QAbstractTableModel 与 QItemDelegate关系

首先强调一下,上面三点内容是为qt框架的model/view架构服务的。model是数据层,顾名思义存储的是数据,包括文字、图片等内容,主要包括QAbstractListModel QAbstractTableModel 。view是展示层,用户看到的就是view层,主要包括qlistview qtableview。model需要在view中呈现出来,这时候就需要渲染,即代理。这部分工作是由QItemDelegate负责的。

1,如果将model view delegate关联起来呢?

[virtual] void QAbstractItemView::setModel(QAbstractItemModel *model)

void QAbstractItemView::setItemDelegate(QAbstractItemDelegate *delegate)

2,如何渲染呢?

要知道对于table和list中数据展示,不仅形式多种多样,而且还有位置、对齐、尺寸等很多内容需要兼顾,如何把握好呢?--采用qitemdelegate对每一个单元格进行渲染。

[pure virtual] void QAbstractItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const

This pure abstract function must be reimplemented if you want to provide custom rendering. Use the painter and style option to render the item specified by the item index.

If you reimplement this you must also reimplement sizeHint().

[virtual] void QItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const

Reimplemented from QAbstractItemDelegate::paint().

Renders the delegate using the given painter and style option for the item specified byindex.

When reimplementing this function in a subclass, you should update the area held by the option's rect variable, using the option's state variable to determine the state of the item to be displayed, and adjust the way it is painted accordingly.

重载QItemDelegate的paint函数进行内容绘制,此时图片采用drawimage,文字采用drawtext,分析此函数,重点是明白三个参数的具体意义。

首先先去领悟一下官方文档中的解释。

对于第1个参数painter,画笔。无需多言,完成view的绘制;

对于第2个参数option,类型是QStyleOptionViewItem。包含了描述一个widget所需要的所有参数,比如位置和尺寸rect,状态state、画板palette。用法如:

option.state & QStyle::State_Selected

option.rect.width()

option.palette.highlightedText()

QStyleOption类的作用就是用于显示用的。该类的成员变量有,QRect,QFont等。都是用于控制item的显示使用的。

QRect,用于控制item的大小。QFont,用于控制item的字体。QPalette,用于控制item的颜色。

对于第3个参数index,用来定位model中的数据。其中column()获取当前index指向的item在第几列,row()获取当前index指向的item在第几行,data()获取当前item中的数据。

3,重载paint完成自定义渲染看似可以解决在单元格内指定位置处放置恰当控件的问题,但并不完全适用。因为painter只能drawText drawImage等一部分控件,对于painter不能绘制的控件,例如QMovie等,就无法实现将其显示在单元格内。面对此类型问题,可以采用自定义单元格控件的方法解决。看如下一段代码:

QStandardItemModel model(4, 2);
	QTableView tableView;
	tableView.horizontalHeader()->setDefaultSectionSize(162);
	tableView.verticalHeader()->setDefaultSectionSize(188);
	tableView.setModel(&model);

	CSpinBoxDelegate delegate;
	tableView.setItemDelegate(&delegate);

	for (int row = 0; row < 4; ++row) {
		for (int column = 0; column < 2; ++column) {
			QModelIndex index = model.index(row, column, QModelIndex());
			if (0 == row % 2)
			{
				CCatcherView* view = new CCatcherView;
				tableView.setIndexWidget(index, view);
			}
			else
			{
				model.setData(index, QVariant(row + column));
			}
		}
	}
           

调用QAbstractItemView类的setIndexWidget方法,在指定的index处插入合适的自定义widget。自定义widget内可以包括已经按照需求布局好的各类控件。如,左上角放一个label,右下角放一个button等等。该处理方法会造成单元格不可编辑,造成无法通过editor函数组来进行单元格内容和控件的更新。鉴于此,可以通过信号-槽或者绑定事件处理函数的方法对view对象进行处理。

4,editor函数组。

有四个函数:

//创建编辑器
    QWidget * createEditor(QWidget *parent, const QStyleOptionViewItem &, const QModelIndex &) const;
    //为编辑器设置数据
    void setEditorData(QWidget* editor,const QModelIndex &index) const;
    //将数据写入到模型
    void setModelData(QWidget* editor,QAbstractItemModel *model, const QModelIndex &index) const;
    //更新编辑器布局
    void updateEditorGeometry(QWidget* editor,const QStyleOptionViewItem &option, const QModelIndex &index) const;
           

继续阅读