天天看點

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;
           

繼續閱讀