GitHub:GitHub - mygit03/ModelDelegate: 在QTableView中使用各种自定义委托 包括ComboBox、DoubleSpinBox、CheckBox以及设置列只读
itemdelegate.h
#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H
#include <QItemDelegate>
#include <QStyledItemDelegate>
/*
* ReadOnly
*/
class ReadOnlyDelegate : public QItemDelegate
{
Q_OBJECT
public:
ReadOnlyDelegate(QObject *parent = 0): QItemDelegate(parent) {}
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(QMap<int,QString> 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:
QMap<int,QString> mapItems; //下拉框列表项
};
/*
* 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; //设置复选框的列
};
/*
* ColorDelegate
*/
class ColorDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
ColorDelegate(QObject *parent = 0);
protected:
void paint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index) const;
private:
};
/*
* QProgressBar
*/
class ProgressBarDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
ProgressBarDelegate(QObject *parent = 0);
void setColumn(int col, int min, int max);
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
return NULL;
}
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;
int maxValue; // 设置最大值
int minValue; // 设置最小值
QPoint m_iMousePoint;
int m_iMouseType;
};
/*
* calendar
*/
class DateDelegate : public QItemDelegate
{
Q_OBJECT
public:
DateDelegate(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;
};
/*
* TimeEdit
*/
class TimeDelegate : public QItemDelegate
{
Q_OBJECT
public:
TimeDelegate(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;
};
/*
* DoubleLineEdit
*/
class DoubleLineEditDelegate : public QItemDelegate
{
Q_OBJECT
public:
DoubleLineEditDelegate(QObject *parent = 0);
void setRange(double bottom, double top, int decimals = 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;
private:
int min; //最小值
int max; //最大值
int dec; //小数位数
};
#endif // ITEMDELEGATE_H
itemdelegate.cpp
#include "itemdelegate.h"
#include <QComboBox>
#include <QDoubleSpinBox>
#include <QDateEdit>
#include <QTimeEdit>
#include <QLineEdit>
#include <QDoubleValidator>
#include <QMouseEvent>
#include <QPainter>
#include <QStyleOption>
#include <QApplication>
#include <QDebug>
/****************************************************
* ComboDelegate
****************************************************/
ComboDelegate::ComboDelegate(QObject *parent) :
QItemDelegate(parent)
{
}
void ComboDelegate::setItems(QMap<int,QString> items)
{
mapItems = items;
}
QWidget *ComboDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
QComboBox *editor = new QComboBox(parent);
QMap<int,QString>::const_iterator it = mapItems.begin();
while (it != mapItems.end())
{
editor->addItem(it.value(),it.key());
++it;
}
editor->installEventFilter(const_cast<ComboDelegate*>(this));
return editor;
}
void ComboDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
QVariant data =index.model()->data(index);
QComboBox *box = static_cast<QComboBox*>(editor);
int i=box->findData(data);
box->setCurrentIndex(i);
}
void ComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QComboBox *box = static_cast<QComboBox*>(editor);
QVariant data = box->itemData(box->findText(box->currentText()));
model->setData(index,data);
}
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.000001);
editor->setDecimals(6);
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);
}
}
/****************************************************
* ProgressBarDelegate
****************************************************/
ProgressBarDelegate::ProgressBarDelegate(QObject *parent) :
QStyledItemDelegate(parent)
{
}
void ProgressBarDelegate::setColumn(int col, int min, int max)
{
column = col;
maxValue = max;
minValue = min;
}
// 绘制进度条
void ProgressBarDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
if (index.column() == column) {
QStyleOptionProgressBar bar;
bar.rect = option.rect;
bar.progress = index.data().toInt();
bar.maximum = maxValue;
bar.minimum = minValue;
bar.text = QString("%1%").arg(bar.progress);
bar.textAlignment = Qt::AlignCenter;
bar.textVisible = true;
if (option.rect.contains(m_iMousePoint))
{
switch (m_iMouseType)
{
case 0:
bar.state |= QStyle::State_MouseOver;
break;
case 1:
bar.state |= QStyle::State_Sunken;
break;
default:
break;
}
}
//
// 设置进度条样式和QWidget一样
QWidget widget;
widget.setStyleSheet("QWidget{border:none;}");
//
QApplication::style()->drawControl(QStyle::CE_ProgressBar, &bar, painter,&widget);
}
else {
QStyledItemDelegate::paint(painter, option, index);
}
}
bool ProgressBarDelegate::editorEvent(QEvent *event,QAbstractItemModel *model,const QStyleOptionViewItem &option,const QModelIndex &index)
{
bool bRepaint = false;
if(index.column() == column)
{
QMouseEvent* e =(QMouseEvent*)event;
m_iMousePoint = e->pos();
// 鼠标位于按钮之上
if (!option.rect.contains(m_iMousePoint))
{
return false;
}
bRepaint = true;
switch (event->type())
{
// 鼠标滑过
case QEvent::MouseMove:
{
m_iMouseType = 0;
break;
}
// 鼠标按下
case QEvent::MouseButtonPress:
{
m_iMouseType = 1;
//model->setData(index, 50); // 用于测试
break;
}
// 鼠标释放
case QEvent::MouseButtonRelease:
{
break;
}
default:
break;
}
}
return bRepaint;
}
/****************************************************
* DateDelegate
****************************************************/
DateDelegate::DateDelegate(QObject *parent) :
QItemDelegate(parent)
{
}
QWidget *DateDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
QDateEdit *editor = new QDateEdit(parent);
editor->setDisplayFormat("yyyy-MM-dd");
editor->setCalendarPopup(true);
return editor;
}
void DateDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
QString str =index.model()->data(index).toString();
QDateEdit *pDate = static_cast<QDateEdit*>(editor);
pDate->setDate(QDate::fromString(str,"yyyy-MM-dd"));
}
void DateDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QDateEdit *pDate = static_cast<QDateEdit*>(editor);
QString str = pDate->date().toString("yyyy-MM-dd");
model->setData(index,str);
}
void DateDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
editor->setGeometry(option.rect);
}
/****************************************************
* TimeDelegate
****************************************************/
TimeDelegate::TimeDelegate(QObject *parent) :
QItemDelegate(parent)
{
}
QWidget *TimeDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
QTimeEdit *editor = new QTimeEdit(parent);
editor->setDisplayFormat("hh:mm:ss");
editor->setCalendarPopup(true);
return editor;
}
void TimeDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
QString str =index.model()->data(index).toString();
QTimeEdit *pTime = static_cast<QTimeEdit*>(editor);
pTime->setTime(QTime::fromString(str,"hh:mm:ss"));
}
void TimeDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QTimeEdit *pTime = static_cast<QTimeEdit*>(editor);
QString str = pTime->time().toString("hh:mm:ss");
model->setData(index,str);
}
void TimeDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
editor->setGeometry(option.rect);
}
/****************************************************
* DoubleLineEditDelegate
****************************************************/
DoubleLineEditDelegate::DoubleLineEditDelegate(QObject *parent) :
QItemDelegate(parent)
{
min = 0;
max = 99;
}
void DoubleLineEditDelegate::setRange(double bottom, double top, int decimals)
{
min = bottom;
max = top;
dec = decimals;
}
QWidget *DoubleLineEditDelegate::createEditor(QWidget *parent,const QStyleOptionViewItem &/*option*/,const QModelIndex &/*index*/) const
{
QLineEdit *editor = new QLineEdit(parent);
//editor->setValidator(new QDoubleValidator(min, max, dec,editor));
QRegExp rx("^(-?[0]|-?[1-9][0-9]{0,5})(?:\\.\\d{1,6})?$|(^\\t?$)");
QRegExpValidator *pReg = new QRegExpValidator(rx, editor);
editor->setValidator(pReg);
return editor;
}
void DoubleLineEditDelegate::setEditorData(QWidget *editor,const QModelIndex &index) const
{
QString str =index.model()->data(index).toString();
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
lineEdit->setText(str);
}
void DoubleLineEditDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
QLineEdit *lineEdit = static_cast<QLineEdit*>(editor);
QString str = lineEdit->text();
model->setData(index,str);
}
void DoubleLineEditDelegate::updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
editor->setGeometry(option.rect);
}
ColorDelegate::ColorDelegate(QObject *parent /*= 0*/)
{
}
void ColorDelegate::paint(QPainter* painter,const QStyleOptionViewItem& option,const QModelIndex& index) const
{
QStyleOptionViewItem op(option);
op.font.setBold(true);
//QVariant value = index.data();
//if (value.toDouble() > 2)
//{
// op.palette.setColor(QPalette::Text, Qt::red);
//}
QStyledItemDelegate::paint(painter, op, 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));
}
}
参考文档: