在QTableView中使用各種自定義委託 包括ComboBox、DoubleSpinBox、CheckBox以及設定列只讀
阿新 • • 發佈:2019-01-07
itemdelegate.h
itemdelegate.cpp#ifndef ITEMDELEGATE_H #define ITEMDELEGATE_H #include <QItemDelegate> #include <QStyledItemDelegate> /* * ReadOnly */ class ReadOnlyDelegate : public QItemDelegate { Q_OBJECT public: ReadOnlyDelegate(QObject *parent = 0): QItemDelegate(parent) {} void setItems(QStringList items); QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { return NULL; } }; /* * ComboBox */ class ComboDelegate : public QItemDelegate { Q_OBJECT public: ComboDelegate(QObject *parent = 0); void setItems(QStringList items); 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; private: QStringList m_sItemList; }; /* * DoubleSpinBox */ class SpinBoxDelegate : public QItemDelegate { Q_OBJECT public: SpinBoxDelegate(QObject *parent = 0); void setRange(double min, double max); 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; private: double minValue; double maxValue; }; /* * CheckBox */ class CheckBoxDelegate : public QStyledItemDelegate { Q_OBJECT public: CheckBoxDelegate(QObject *parent = 0); void setColumn(int col); protected: void paint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index) const; bool editorEvent(QEvent *event,QAbstractItemModel *model,const QStyleOptionViewItem &option,const QModelIndex &index); private: int column; //設定複選框的列 }; #endif // ITEMDELEGATE_H
引用程式碼:#include "itemdelegate.h" #include <QComboBox> #include <QDoubleSpinBox> #include <QMouseEvent> #include <QPainter> #include <QStyleOption> #include <QApplication> #include <QDebug> /* * ComboDelegate */ ComboDelegate::ComboDelegate(QObject *parent) : QItemDelegate(parent) { } //自定義下拉框列表項 void ComboDelegate::setItems(QStringList items) { m_sItemList = items; } QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const { QComboBox *editor = new QComboBox(parent); editor->addItems(m_sItemList); editor->installEventFilter(const_cast<ComboDelegate*>(this)); return editor; } void ComboDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const { QString str =index.model()->data(index).toString(); QComboBox *box = static_cast<QComboBox*>(editor); int i=box->findText(str); box->setCurrentIndex(i); } void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QComboBox *box = static_cast<QComboBox*>(editor); QString str = box->currentText(); model->setData(index,str); } void ComboDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const { editor->setGeometry(option.rect); } /* * SpinBoxDelegate */ SpinBoxDelegate::SpinBoxDelegate(QObject *parent) : QItemDelegate(parent) { //初始化最大最小值 minValue = 1.00; maxValue = 100.00; } void SpinBoxDelegate::setRange(double min, double max) { minValue = min; maxValue = max; } QWidget *SpinBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QDoubleSpinBox *editor = new QDoubleSpinBox(parent); editor->setMinimum(minValue); editor->setMaximum(maxValue); editor->setSingleStep(0.01); return editor; } void SpinBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { double value = index.model()->data(index, Qt::EditRole).toDouble(); QDoubleSpinBox *spinBox = static_cast <QDoubleSpinBox*>(editor); spinBox->setValue(value); } void SpinBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QDoubleSpinBox *spinBox = static_cast <QDoubleSpinBox*>(editor); spinBox->interpretText(); double value = spinBox->value(); model->setData(index, value, Qt::EditRole); } void SpinBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); } /* * CheckBoxDelegate */ static QRect CheckBoxRect(const QStyleOptionViewItem &viewItemStyleOptions)/*const*/ { //繪製按鈕所需要的引數 QStyleOptionButton checkBoxStyleOption; //按照給定的風格引數 返回元素子區域 QRect checkBoxRect = QApplication::style()->subElementRect( QStyle::SE_CheckBoxIndicator, &checkBoxStyleOption); //返回QCheckBox座標 QPoint checkBoxPoint(viewItemStyleOptions.rect.x() + viewItemStyleOptions.rect.width() / 2 - checkBoxRect.width() / 2, viewItemStyleOptions.rect.y() + viewItemStyleOptions.rect.height() / 2 - checkBoxRect.height() / 2); //返回QCheckBox幾何形狀 return QRect(checkBoxPoint, checkBoxRect.size()); } CheckBoxDelegate::CheckBoxDelegate(QObject *parent): QStyledItemDelegate(parent) { } void CheckBoxDelegate::setColumn(int col) { column = col; } // 繪製複選框 void CheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,const QModelIndex& index)const { bool checked = index.model()->data(index, Qt::DisplayRole).toBool(); if(index.column() == column){ QStyleOptionButton checkBoxStyleOption; checkBoxStyleOption.state |= QStyle::State_Enabled; checkBoxStyleOption.state |= checked? QStyle::State_On : QStyle::State_Off; checkBoxStyleOption.rect = CheckBoxRect(option); QApplication::style()->drawControl(QStyle::CE_CheckBox,&checkBoxStyleOption,painter); }else{ QStyledItemDelegate::paint(painter, option, index); } } // 響應滑鼠事件,更新資料 bool CheckBoxDelegate::editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option, const QModelIndex &index) { if(index.column() == column){ if((event->type() == QEvent::MouseButtonRelease) || (event->type() == QEvent::MouseButtonDblClick)){ QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event); if(mouseEvent->button() != Qt::LeftButton || !CheckBoxRect(option).contains(mouseEvent->pos())){ return true; } if(event->type() == QEvent::MouseButtonDblClick){ return true; } }else if(event->type() == QEvent::KeyPress){ if(static_cast<QKeyEvent*>(event)->key() != Qt::Key_Space && static_cast<QKeyEvent*>(event)->key() != Qt::Key_Select){ return false; } }else{ return false; } bool checked = index.model()->data(index, Qt::DisplayRole).toBool(); int data = checked ? 0 : 1; //互逆 return model->setData(index, data, Qt::EditRole); }else{ return QStyledItemDelegate::editorEvent(event, model, option, index); } }
for(int col = 0; col < 4; ++col) { if(col == 0) { ReadOnlyDelegate *readOnly = new ReadOnlyDelegate; setItemDelegateForColumn(col,readOnly); } if(col == 1) { CheckBoxDelegate *checkBox = new CheckBoxDelegate; checkBox->setColumn(1); setItemDelegateForColumn(col,checkBox); } if(col == 2) { SpinBoxDelegate *spinBox = new SpinBoxDelegate; setItemDelegateForColumn(col,spinBox); } if(col == 3) { ComboDelegate *combo = new ComboDelegate; combo->setItems(items); setItemDelegateForColumn(col,combo); } for(int row = 0; row < 4; ++row) { QModelIndex index = model->index(row, col, QModelIndex()); model->setData(index, QString("%1%2").arg(row).arg(col)); } }
參考文件: