在QTableView中使用各种自定义委托 包括ComboBox、DoubleSpinBox、CheckBox以及设置列只读

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));
        }
    }

参考文档:

QTableView数据刷新

学习记录-QTableView自定义委托实现QCheckBox复选框

  • 11
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值