在上一章學習 25.QT-模型視圖 後,本章接着學習視圖委託html
視圖委託(Delegate)簡介設計模式
因爲模型負責組織數據,而視圖負責顯示數據,因此當用戶想修改顯示的數據時,就要經過視圖中的委託來完成編輯器
視圖委託相似於傳統的MVC設計模式裏的Controller(控制器)角色函數
初探自定義委託類
post
QAbstractItemDelegate類中的關鍵虛函數學習
QWidget * createEditor( QWidget * parent, QStyleOptionViewItem & option, QModelIndex & index ) ; //建立編輯器,並返回該編輯器, option包含了該數據項的具體信息(好比:數據項窗口大小,字體格式,對齊方式,圖標位於字體的哪一個位置等)、index 包含了該數據項的內容(好比:text信息,背景色等) void updateEditorGeometry ( QWidget * editor, QStyleOptionViewItem & option, QModelIndex &index ); //該函數裏,能夠經過editor->setGeometry()更新編輯組件大小,保證editor顯示的位置及大小 //大小能夠經過option.rect獲取數據項窗口大小 void setEditorData ( QWidget * editor, const QModelIndex & index ); //經過索引值,將模型裏的數據提取到編輯器內容裏 void setModelData ( QWidget * editor, QAbstractItemModel * model, QModelIndex & index ); //經過索引值, 根據editor 的數據更新model的數據。 void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) ; //複製繪畫數據項的顯示和編輯
QAbstractItemDelegate類中的關鍵信號字體
void closeEditor ( QWidget * editor, QAbstractItemDelegate::EndEditHint hint = NoHint ); //當用戶關閉編輯器後,就會發出這個信號。 // hint 參數用來指定當用戶完成編輯後,應該顯示什麼標記,用來提示用戶已完成編輯 void commitData ( QWidget * editor ) ; //當完成編輯數據後,發送該信號,表示有新數據提交到模型中
咱們以編輯某個數據項爲例:ui
接下來,咱們重寫上面函數,來自定義一個QCostomizedDelegate委託類url
效果以下spa
QCustomizedDelegate.h:
#ifndef QCUSTOMIZEDDELEGATE_H #define QCUSTOMIZEDDELEGATE_H #include <QItemDelegate> #include <QtGui> class QCustomizedDelegate : public QItemDelegate { Q_OBJECT public: explicit QCustomizedDelegate(QObject *parent = 0); QWidget * createEditor( QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index ) 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; }; #endif // QCUSTOMIZEDDELEGATE_H
QCustomizedDelegate.cpp:
#include "QCustomizedDelegate.h"
QCustomizedDelegate::QCustomizedDelegate(QObject *parent) : QItemDelegate(parent) { } QWidget* QCustomizedDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { if(index.column()==1) //第1列 班級 { QComboBox *Cbox = new QComboBox(parent); Cbox->addItems(QStringList()<<"1班"<<"2班"<<"3班"<<"4班"<<"5班"); return Cbox; } else if(index.column()==2) //第2列 分數 { QSpinBox *Sbox = new QSpinBox(parent); Sbox->setRange(0,150); return Sbox; } return QItemDelegate::createEditor(parent, option, index); //第0列,則選擇默認編輯器 } void QCustomizedDelegate::setEditorData ( QWidget * editor, const QModelIndex & index ) const { if(index.column()==1) //第1列 班級 { QComboBox *Cbox = dynamic_cast<QComboBox*>(editor); Cbox->setCurrentIndex(Cbox->findText( index.data(Qt::DisplayRole).toString())); } else if(index.column()==2) //第2列 分數 { QSpinBox *Sbox = dynamic_cast<QSpinBox*>(editor); Sbox->setValue(index.data(Qt::DisplayRole).toInt()); } else QItemDelegate::setEditorData(editor, index); } void QCustomizedDelegate::setModelData ( QWidget * editor, QAbstractItemModel * model, const QModelIndex & index ) const { if(index.column()==1) //第1列 班級 { QComboBox *Cbox = dynamic_cast<QComboBox*>(editor); model->setData(index,Cbox->currentText(),Qt::DisplayRole); } else if(index.column()==2) //第2列 分數 { QSpinBox *Sbox = dynamic_cast<QSpinBox*>(editor); model->setData(index,Sbox->value(),Qt::DisplayRole); } else QItemDelegate::setModelData(editor, model, index); } void QCustomizedDelegate::updateEditorGeometry ( QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index ) const { editor->setGeometry(option.rect); }
而後,再經過視圖的setItemDelegate(QAbstractItemDelegate * delegate )成員函數設置咱們自定義的委託類對象便可
深刻自定義委託類
以前咱們寫的自定義委託,每次都須要雙擊某個數據項,才能彈出編輯器
那如何讓委託一直呈如今視圖顯示上呢?
步驟以下:
其中QApplication::style()->drawControl()函數參數以下所示:
QApplication::style()->drawControl (ControlElement element,
constQStyleOption * option,
QPainter *painter, const QWidget * widget = 0 ) ; //繪畫組件 // element: 元素,用來指定控件樣式,好比: QStyle::CE_CheckBox 表示繪畫的widget是一個text文本的複選框 // option:選項,用來繪製控件所需的全部參數好比option.rect(設置組件大小位置), option.state(設置組件狀態)
//其中option. state成員值常見的有: QStyle::State_Enabled //表示該組件是激活的,能夠被用戶操做 QStyle::State_On //表示該組件樣式是被選上的 QStyle::State_Off //表示該組件樣式是未被選中的 QStyle::State_MouseOver //表示表示該組件樣式是:鼠標停留在組件上面的樣子 QStyle::State_Sunken //表示該組件樣式是:鼠標按壓下的組件樣子 QStyle::State_HasEditFocus //表示該組件是否有編輯焦點 // painter:誰來繪畫 // widget = 0:若是該widget爲0,則表示使用QT自帶的風格
示例-自定義一個QCostomizedDelegate委託類
效果以下
代碼以下
QCustomizedDelegate.h:
#ifndef QCUSTOMIZEDDELEGATE_H #define QCUSTOMIZEDDELEGATE_H #include <QItemDelegate> #include <QtGui> #include "ProgressBar.h" class QCustomizedDelegate : public QItemDelegate { Q_OBJECT //m_bar:溫度臺的當前溫度進度條 QScopedPointer<QProgressBar> m_bar ; public: explicit QCustomizedDelegate(QObject *parent = 0); void paint ( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const; bool editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index ); }; #endif // QCUSTOMIZEDDELEGATE_H
QCustomizedDelegate.cpp:
#include "QCustomizedDelegate.h" #include "ProgressBar.h" QCustomizedDelegate::QCustomizedDelegate(QObject *parent) : QItemDelegate(parent), m_bar(new QProgressBar()) { m_bar->setStyleSheet(qApp->styleSheet()); //設置風格 } void QCustomizedDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const { if(index.column()==1 && index.data().type() == QVariant::Int) //判斷列數,並判斷索引值是否int型(溫度是經過int型值表示的) { int radio=14; int top = option.rect.top() + radio; int left = option.rect.left() + radio; int width = option.rect.width() - 2 * radio; int height = option.rect.height() - 2 * radio; QStyleOptionProgressBar bar; //設置參數 bar.rect.setRect(left, top, width, height); bar.state = QStyle::State_Enabled; bar.progress = index.data().toInt(); bar.maximum = 100; bar.minimum = 0; bar.textVisible = true; bar.text = QString("當前溫度:%1°").arg(bar.progress); bar.textAlignment = Qt::AlignCenter; QApplication::style()->drawControl(QStyle::CE_ProgressBar,&bar,painter, m_bar.data()); } else { QItemDelegate::paint(painter,option,index); } } bool QCustomizedDelegate::editorEvent ( QEvent * event, QAbstractItemModel * model, const QStyleOptionViewItem & option, const QModelIndex & index ) { if(event->type() == QEvent::MouseButtonDblClick) //禁止雙擊編輯 { return true; } return QItemDelegate::editorEvent(event,model,option,index); }