Qt|表格代理的实现及使用代码qtableview和qtablewidget均适用

参考:
QTableView表格控件代理详解
https://blog.csdn.net/u010031316/article/details/120366295

示例程序


运行环境:WIN10,VS2022,QT6.3
创建的QtWidgetApplication项目,解决方案目录及main主函数如下图:
VS
qrc资源文件中就放了几个从 阿里巴巴矢量图库下载的几张图:
qrc

ui中就部署了一个qtablewidget,如图所示:
ui部署图
分模块代码

ComboBox委托:

// ComboBox委托
class ComboBoxDelegate :public QItemDelegate
{
	Q_OBJECT

public:
	ComboBoxDelegate(QObject* parent = 0) :QItemDelegate(parent)
	{

	}
	// 开始编辑状态
	QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		QComboBox* editor = new QComboBox(parent);
		//if (flag == false)
		//{
		//	return editor;
		//}
		if (m_list.isEmpty())
			return NULL;
		QStandardItemModel* model = new QStandardItemModel(editor);
		for (int i = 0; i < m_list.count(); i++)
		{
			QStandardItem* item = new QStandardItem(m_list.at(i));
			item->setTextAlignment(Qt::AlignCenter);
			item->setToolTip(ip_list.at(i));
			item->setData(ip_list.at(i), Qt::UserRole);
			model->setItem(i, item);
		}
		editor->setModel(model);
		//editor->setCurrentIndex(0);
		editor->setCurrentText(index.data(Qt::EditRole).toString());
		return editor;
	}
	// 正在编辑状态
	void setEditorData(QWidget* editor, const QModelIndex& index)const
	{
		QString text = index.model()->data(index, Qt::EditRole).toString();
		QComboBox* comboBox = static_cast<QComboBox*>(editor);
		connect(comboBox, &QComboBox::currentTextChanged, this, [=](const QString& text) {
			// 用于置脏数据来着 可以根据需求灵活修改
			//emit ComboTextChanged(index, text);
			});
		comboBox->setCurrentText(text);
	}
	// 退出编辑状态
	void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
	{
		//if (flag == false)
		//	return;
		QComboBox* comboBox = static_cast<QComboBox*>(editor);
		QString text = comboBox->currentText();
		QString ip;
		QStandardItemModel* comb_model = dynamic_cast<QStandardItemModel*>(comboBox->model());
		if (comb_model)
		{
			QStandardItem* item = comb_model->item(comboBox->currentIndex());
			ip = item->data(Qt::UserRole).toString();
		}
		if (text != index.data().toString()) {
			//model->blockSignals(true);
			model->setData(index, ip, Qt::UserRole);
			model->setData(index, text, Qt::EditRole);
			//model->setData(index, "", Qt::UserRole+1);
			//model->blockSignals(false);
		}
		//emit ComboTextChanged(index, text);
		//emit sigStudentSeatChange();

	}
	void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		editor->setGeometry(option.rect);
	}
	// 参数数量可以根据需求灵活修改
	void setMenuList(QStringList _site_name_list, QStringList _site_ip_list)
	{
		m_list = _site_name_list;
		ip_list = _site_ip_list;
	}
	// 	void setSignalFlag(bool _flag)
	// 	{
	// 		flag = _flag;
	// 	}

signals:
	// 可以根据需求添加自定义信号进行处理
	//void ComboTextChanged(const QModelIndex& index, const QString text)const;
	//void sigStudentSeatChange(const QTableWidgetItem * _item)const;
private:
	QStringList m_list;
	QStringList ip_list;
	//bool flag;		// true为可编辑状体 false为不可编辑状态
};

状态代理:

// 状态代理
class StatusDelegate : public QStyledItemDelegate
{
	Q_OBJECT
public:
	StatusDelegate(QObject* parent = nullptr) {};
	~StatusDelegate() {}
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:
	QString m_text;
};

状态代理实现cpp:

void StatusDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	const bool enabled = option.state & QStyle::State_Enabled;
	const bool active = option.state & QStyle::State_Active;
	const bool selected = option.state & QStyle::State_Selected;

	if (enabled && active && selected)
		painter->fillRect(option.rect, option.palette.highlight());
	if (enabled && selected && !active) {
		painter->fillRect(option.rect, option.palette.color(QPalette::Inactive, QPalette::Highlight));
	}

	int height = option.rect.height();
	int width = option.rect.width();
	int m_x = option.rect.x() + width / 4 - 5;
	int m_y = option.rect.y() + height / 2 - 5;

	QString site_status = index.data(Qt::UserRole).toString();

	painter->save();
	//QColor brush = Qt::transparent;
	if (index.data(Qt::UserRole).toString() == "关于")
	{
		//brush = QColor(6, 176, 37);
		QPixmap pixmap = QPixmap(8, 8);
		pixmap.load(QString(":/QtDelegateTest/res/关于.png"));
		painter->drawPixmap(m_x - 10, m_y, pixmap);
		painter->drawText(m_x, option.rect.y(), width * 3 / 4, height, Qt::AlignCenter, site_status);
	}
	else if (index.data(Qt::UserRole).toString() == "设置")
	{
		//brush = QColor(177, 177, 177);
		QPixmap pixmap = QPixmap(8, 8);
		pixmap.load(QString(":/QtDelegateTest/res/设置.png"));
		painter->drawPixmap(m_x - 10, m_y, pixmap);
		painter->drawText(m_x, option.rect.y(), width * 3 / 4, height, Qt::AlignCenter, site_status);
	}
	else if (index.data(Qt::UserRole).toString() == "退出")
	{
		//brush = QColor(255, 0, 0);
		QPixmap pixmap = QPixmap(8, 8);
		pixmap.load(QString(":/QtDelegateTest/res/退出.png"));
		painter->drawPixmap(m_x - 10, m_y, pixmap);
		painter->drawText(m_x, option.rect.y(), width * 3 / 4, height, Qt::AlignCenter, site_status);
	}
	painter->restore();
}

bool StatusDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
	return QStyledItemDelegate::editorEvent(event, model, option, index);
}

只读代理:

//只读代理
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 nullptr;
	}
};

spinBox委托:

//spinBox委托
class SpinBoxDelegate
	: public QItemDelegate
{
	Q_OBJECT
public:
	SpinBoxDelegate(QObject* parent = 0) :QItemDelegate(parent) { m_minimum = 0; m_maxinum = 0; m_singleStep = 0; }
	QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		QSpinBox* editor = new QSpinBox(parent);
		editor->setMinimum(m_minimum);
		editor->setMaximum(m_maxinum);
		editor->setSingleStep(m_singleStep);
		return editor;
	}

	void setEditorData(QWidget* editor, const QModelIndex& index)const
	{
		int value = index.model()->data(index, Qt::EditRole).toInt();
		QSpinBox* spinbox = static_cast<QSpinBox*>(editor);
		// 此处注释部分为Qt5实现方法 为了解决函数重载的信号绑定问题 Qt升级后将函数重载的函数更改了名字如下所示
		connect(spinbox, /*static_cast<void (QSpinBox::*)(const QString&)>*/(&QSpinBox::/*valueChanged*/textChanged), this, [=](const QString& value)
			{
				emit SpinBoxValueChanged(index, value);
			});
		spinbox->setValue(value);
	}
	void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
	{
		QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
		int value = spinBox->value();
		if (model->data(index, Qt::EditRole).toInt() != value)
			model->setData(index, value, Qt::EditRole);
	}

	void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		editor->setGeometry(option.rect);
	}

	void setSpinBoxProperty(double minimum, double maxinum, double singleStep)
	{
		m_minimum = (int)minimum;
		m_maxinum = (int)maxinum;
		m_singleStep = (int)singleStep;
	}

signals:
	void SpinBoxValueChanged(const QModelIndex& index, const QString& value)const;

private:
	int m_minimum;		// 最小值
	int m_maxinum;		// 最大值
	int m_singleStep;	// 每步调整大小
};

DoubleSpinBox委托:

// DoubleSpinBox委托
class DoubleSpinBoxDelegate
	: public QItemDelegate
{
	Q_OBJECT
public:
	DoubleSpinBoxDelegate(QObject* parent = 0) :QItemDelegate(parent) { m_minimum = 0; m_maxinum = 0; m_singleStep = 0; m_decimals = 0; }
	QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		QDoubleSpinBox* editor = new QDoubleSpinBox(parent);
		editor->setMinimum(m_minimum);
		editor->setMaximum(m_maxinum);
		editor->setSingleStep(m_singleStep);
		editor->setDecimals(m_decimals);
		return editor;
	}
	void setEditorData(QWidget* editor, const QModelIndex& index)const
	{
		double value = index.model()->data(index, Qt::EditRole).toDouble();
		QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
		// 此处注释部分为Qt5实现方法 为了解决函数重载的信号绑定问题 Qt升级后将函数重载的函数更改了名字如下所示
		connect(doubleSpinBox, /*static_cast<void (QDoubleSpinBox::*)(const QString&)>*/(&QDoubleSpinBox::textChanged/*valueChanged*/), this, [=](const QString& value)
			{
				emit DoubleSpinBoxValueChanged(index, value);
			});
		doubleSpinBox->setValue(value);
	}
	void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
	{
		QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
		double value = doubleSpinBox->value();
		if (model->data(index, Qt::EditRole).toDouble() != value)
			model->setData(index, QString::number(value, 'f', m_decimals), Qt::EditRole);
	}
	void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		editor->setGeometry(option.rect);
	}

	void setDoubleSpinBoxProperty(double minimum, double maxinum, double singleStep, int decimals)
	{
		m_minimum = minimum;
		m_maxinum = maxinum;
		m_singleStep = singleStep;	// 每步调整多少
		m_decimals = decimals;	// 小数点后几位
	}

signals:
	void DoubleSpinBoxValueChanged(const QModelIndex& index, const QString& value)const;

private:
	double m_minimum;
	double m_maxinum;
	double m_singleStep;
	int m_decimals;
};

checkBox勾选框代理:

// checkBox勾选框代理
class CheckBoxDelegate :public QStyledItemDelegate
{
	Q_OBJECT
public:
	CheckBoxDelegate(QObject* parent = 0) {}
protected:
	virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
	virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const;
	virtual bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);

signals:
	void CheckStateChanged(const QModelIndex& _index, int _state);
};

checkBox勾选框代理实现cpp:

static QRect CheckBoxRect(const QStyleOptionViewItem& viewItemStyleOptions)
{
	QStyleOptionButton checkBoxStyleOption;
	QRect checkBoxRect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkBoxStyleOption);
	QPoint checkBoxPoint(viewItemStyleOptions.rect.x() + viewItemStyleOptions.rect.width() / 2 - checkBoxRect.width() / 2,
		viewItemStyleOptions.rect.y() + viewItemStyleOptions.rect.height() / 2 - checkBoxRect.height() / 2);
	return QRect(checkBoxPoint, checkBoxRect.size());
}

QSize CheckBoxDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	QStyleOptionViewItem opt = option;
	QSize opt_size = QStyledItemDelegate::sizeHint(option, index);
	return QSize(40,opt_size.height());
}

void CheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	//const bool enabled = option.state & QStyle::State_Enabled;
	//const bool active = option.state & QStyle::State_Active;
	//const bool selected = option.state & QStyle::State_Selected;

	 绘制原生背景
	//if (enabled && active && selected)
	//	painter->fillRect(option.rect, option.palette.highlight());
	//if (enabled && selected && !active)
	//	painter->fillRect(option.rect, option.palette.color(QPalette::Inactive, QPalette::Highlight));

	QStyleOptionViewItem opt = option;
 	bool checked = index.model()->data(index, Qt::DisplayRole).toBool();
	QStyleOptionButton checkBoxStyleOption;
	checkBoxStyleOption.state |= QStyle::State_Enabled;
	checkBoxStyleOption.state |= checked ? QStyle::State_On : QStyle::State_Off;
	checkBoxStyleOption.rect = CheckBoxRect(opt);
	painter->setPen(Qt::black);
	QRect text_rect = CheckBoxRect(opt);
	text_rect.setWidth(text_rect.width() + 20);
	painter->drawText(text_rect, Qt::AlignRight | Qt::AlignVCenter, QString::number(index.row() + 1));

	QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxStyleOption, painter);
}

bool CheckBoxDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
	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();
	if (checked == false)
		emit CheckStateChanged(index, 1);
	else
		emit CheckStateChanged(index, 0);
	return model->setData(index, !checked, Qt::EditRole);
}

表头添加checkBox:

//	表头添加checkBox
class CCheckBoxHeaderView : public QHeaderView
{
	Q_OBJECT
public:
	CCheckBoxHeaderView(int checkBoxColumnID, Qt::Orientation orientation, QWidget* parent);
	~CCheckBoxHeaderView() {}
	void setChecked(bool ischeck)
	{
		m_checkBoxIsOn = ischeck;
		updateSection(m_checkBoxColumnId);
	}

	void setSorted(bool isSort)
	{
		m_isSort = isSort;
	}

protected:
	void mousePressEvent(QMouseEvent* event);
	void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const;

signals:
	void sig_AllChecked(bool);

private:
	int m_checkBoxColumnId;
	bool m_checkBoxIsOn;
	bool m_isSort;
};

表头添加checkBox实现cpp:

CCheckBoxHeaderView::CCheckBoxHeaderView(int checkBoxColumnId, Qt::Orientation orientation, QWidget* parent)
	: QHeaderView(orientation, parent)
{
	m_checkBoxColumnId = checkBoxColumnId;
	m_checkBoxIsOn = false;
	m_isSort = false;
}

void CCheckBoxHeaderView::paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const
{
	painter->save();
	QHeaderView::paintSection(painter, rect, logicalIndex);
	
	painter->restore();
	if (logicalIndex == m_checkBoxColumnId)
	{
		QStyleOptionButton option;
		int width = 3;
		for (int i = 0; i < logicalIndex; ++i)
			width += sectionSize(i);
		option.rect = QRect(width, 5, 15, 15);
		if (m_checkBoxIsOn)
			option.state = QStyle::State_On;
		else
			option.state = QStyle::State_Off;
		this->style()->drawControl(QStyle::CE_CheckBox, &option, painter);
	}
}

void CCheckBoxHeaderView::mousePressEvent(QMouseEvent* event)
{
	int x = event->pos().x();
	int y = event->pos().y();
	if (visualIndexAt(event->pos().x()) == m_checkBoxColumnId)
	{
		//if (event->pos().x() >= 3 && event->pos().x() <= 18 && event->pos().y() >= 5 && event->pos().y() <= 20)
		{
			this->setSectionsClickable(true);
			if (m_checkBoxIsOn)
				m_checkBoxIsOn = false;
			else
				m_checkBoxIsOn = true;
			this->updateSection(m_checkBoxColumnId);
			// 可以连接这个信号将下面所有checkbox状态改变
			emit sig_AllChecked(m_checkBoxIsOn);
		}
		//else
		//{
		//	this->setSectionsClickable(m_isSort);
		//}
	}
	else
	{
		this->setSectionsClickable(m_isSort);
	}
	QHeaderView::mousePressEvent(event);
}

pushButton代理:

//	pushButton代理
class PushbuttonDelegate : public QItemDelegate
{
	Q_OBJECT
public:
	PushbuttonDelegate(QObject* parent = 0) {}
	~PushbuttonDelegate() {}

protected:
	void paint(QPainter* painter, const QStyleOptionViewItem& option,
		const QModelIndex& index) const;

	bool editorEvent(QEvent* event, QAbstractItemModel* model,
		const QStyleOptionViewItem& option, const QModelIndex& index);
public:
	void setText(const QString& text);

signals:
	void sig_buttonClicked(const QModelIndex& index, const QRect& rect);

private:
	QMap<QModelIndex, QStyleOptionButton*>m_pBtns;
	QString m_text;
};

pushButton代理实现cpp:

void PushbuttonDelegate::setText(const QString& text)
{
	m_text = text;
}

void PushbuttonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
	const QModelIndex& index) const
{
	const bool enabled = option.state & QStyle::State_Enabled;
	const bool active = option.state & QStyle::State_Active;
	const bool selected = option.state & QStyle::State_Selected;

	QStyleOptionButton button;
	button.rect = option.rect.adjusted(6, 6, -6, -6);
	button.text = m_text;
	button.state = option.state;
	button.iconSize = QSize(18, 18);
	QPixmap pixmap = QPixmap(8, 8);
	pixmap.load(QString(":/QtDelegateTest/res/设置.png"));
	button.icon = QIcon(pixmap);

	//! \获取按钮状态
	bool pressed = index.data(Qt::UserRole + 2).toBool();
	button.state |= pressed ? QStyle::State_Sunken : QStyle::State_Raised;

	if (enabled && active && selected)
		painter->fillRect(option.rect, option.palette.highlight());
	if (enabled && selected && !active) {
		painter->fillRect(option.rect, option.palette.color(QPalette::Inactive, QPalette::Highlight));
	}
	button.palette.setColor(QPalette::All, QPalette::ButtonText, painter->pen().color());
	QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
}

bool PushbuttonDelegate::editorEvent(QEvent* event, QAbstractItemModel* model,
	const QStyleOptionViewItem& option, const QModelIndex& index)
{
	if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
		if (QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event)) {
			if (mouseEvent->button() == Qt::LeftButton) {
				bool pressed = false;
				(event->type() == QEvent::MouseButtonPress) ? pressed = true : pressed = false;
				model->setData(index, pressed, /*Button_State_Sunken*/Qt::UserRole + 2);
				if (event->type() == QEvent::MouseButtonPress) {
					/*	QString base_type = model->data(model->index(index.row(), index.column() - 2)).toString();*/
					QStyleOption option_base = option;
					QRect rect = option_base.rect;
					emit sig_buttonClicked(index, rect);
				}
				return true;
			}
		}
	}
	return true;
}

自定义组件:

// 自定义组件
#include <QPushButton>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QObject>
class  CustomWidget
	:public QWidget
{
	Q_OBJECT
public:
	explicit CustomWidget(QWidget* parent = 0);
	~CustomWidget();
public:
	void SetText(QString _text);
	QString GetText();
private slots:
	void SlotButtonclicked();
private:
	QLineEdit* le_path_;
	QPushButton* pb_open_;
	QString exe_path_;
	QHBoxLayout* main_layout_;
};

// 自定义组合代理LineEdit+pushButton
// 结合上面类进行使用 先创建qwidget再把widget放进代理类
class CustomComDelegate
	: public QItemDelegate
{
	Q_OBJECT
public:
	CustomComDelegate(QObject* parent = nullptr);
	~CustomComDelegate();

signals:
	void SignalExePath(const QModelIndex _index, QString _exe_path) const;

protected:
	virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;

	virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;

	virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;

	virtual void setEditorData(QWidget* editor, const QModelIndex& index) const;

	virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;

};

自定义组件实现cpp:

// 自定义组合代理
CustomWidget::CustomWidget(QWidget* parent /*= 0*/)
	:QWidget(parent)
	, exe_path_()
{
	pb_open_ = new QPushButton("...");
	pb_open_->setFixedSize(25, 25);
	le_path_ = new QLineEdit();
	// 设置不可编辑
	le_path_->setEnabled(true);

	main_layout_ = new QHBoxLayout();
	main_layout_->addWidget(le_path_);
	main_layout_->addWidget(pb_open_);
	main_layout_->setContentsMargins(0, 0, 0, 0);
	main_layout_->setSpacing(0);
	this->setLayout(main_layout_);

	connect(pb_open_, &QPushButton::clicked, this, &CustomWidget::SlotButtonclicked);
}

CustomWidget::~CustomWidget()
{

}

void CustomWidget::SlotButtonclicked()
{
	QString exe_path = le_path_->text();
	if (exe_path.isEmpty()) {
		exe_path = QFileDialog::getOpenFileName(this, "选择应用程序路径", "C:/Users/admin/Desktop/", "应用程序(*.exe)");
	}
	else {
		exe_path = QFileDialog::getOpenFileName(this, "选择应用程序路径", exe_path, "应用程序(*.exe)");
	}
	if (!exe_path.isEmpty()) {
		le_path_->setText(exe_path);
	}
}

void CustomWidget::SetText(QString _text)
{
	le_path_->setText(_text);
}

QString CustomWidget::GetText()
{
	return le_path_->text();
}

// 自定义组合代理
CustomComDelegate::CustomComDelegate(QObject* parent /*= nullptr*/)
	:QItemDelegate(parent)
{

}

CustomComDelegate::~CustomComDelegate()
{

}

void CustomComDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	QItemDelegate::paint(painter, option, index);
}

QSize CustomComDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	return QItemDelegate::sizeHint(option, index);
}

QWidget* CustomComDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	CustomWidget* custom_widget = new CustomWidget(parent);
	custom_widget->installEventFilter(const_cast<CustomComDelegate*>(this));
	return custom_widget;
}

void CustomComDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
	QString value = index.model()->data(index, Qt::DisplayRole).toString();
	CustomWidget* custom_widget = qobject_cast<CustomWidget*>(editor);
	if (!value.isEmpty()) {
		custom_widget->SetText(value);
	}
	else {
		QItemDelegate::setEditorData(editor, index);
	}
}

void CustomComDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
	CustomWidget* custom_widget = qobject_cast<CustomWidget*>(editor);
	// 	if (custom_widget->GetText().isEmpty()){
	// 		model->setData(index, "");
	// 	}
	// 	else{
	model->setData(index, custom_widget->GetText());
	emit SignalExePath(index, custom_widget->GetText());
	//}
}

双进度条代理:

// 双进度条代理
class ProgressBarDelegate
	:public QStyledItemDelegate
{
	Q_OBJECT
public:
	ProgressBarDelegate(QObject* parent = nullptr);
	~ProgressBarDelegate();

protected:
	virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;

};

双进度条代理实现cpp:

#include <QStyleOptionProgressBar>

ProgressBarDelegate::ProgressBarDelegate(QObject* parent /*= nullptr*/)
{

}

ProgressBarDelegate::~ProgressBarDelegate()
{

}

void ProgressBarDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	if (index.isValid()) {
		QRect rect = option.rect;
		int m_x = option.rect.x();
		int m_y = option.rect.y();

		// 0是cpu 1是gpu
		//int flag = index.data(Qt::UserRole + 1).toInt();
		//if (flag == 0)
		//{
			// 图标
			QPixmap cpu_pixmap = QPixmap(8, 8);
			cpu_pixmap.load(QString(":/QtDelegateTest/res/CPU.png"));
			painter->drawPixmap(m_x + 5, m_y + 7, cpu_pixmap);
			// CPU进度条
			QStyleOptionProgressBar cpu_bar;
			QRect cpu_bar_rect;
			cpu_bar_rect.setRect(rect.left() + 30, rect.top(), rect.width() - 30, rect.height()/2 - 2);
			cpu_bar.rect = cpu_bar_rect;

			cpu_bar.progress = index.data(Qt::UserRole).toInt();
			cpu_bar.maximum = 100;
			cpu_bar.minimum = 0;
			cpu_bar.textAlignment = Qt::AlignCenter;
			cpu_bar.text = QString::number(cpu_bar.progress) + "%";
			cpu_bar.textVisible = true;
			QApplication::style()->drawControl(QStyle::CE_ProgressBar, &cpu_bar, painter);
		//}
		//else if (flag == 1)
		//{
			QPixmap mem_pixmap = QPixmap(8, 8);
			mem_pixmap.load(QString(":/QtDelegateTest/res/内存.png"));
			painter->drawPixmap(m_x + 5, m_y+option.rect.height()/2 + 7, mem_pixmap);

			// 内存进度条
			QStyleOptionProgressBar mem_bar;
			QRect mem_bar_rect;
			mem_bar_rect.setRect(rect.left() + 30, rect.top()+ rect.height() / 2 + 2, rect.width() - 30, rect.height()/2 - 4);

			mem_bar.progress = index.data(Qt::UserRole+1).toInt();
			mem_bar.maximum = 100;
			mem_bar.minimum = 0;
			mem_bar.textAlignment = Qt::AlignCenter;
			mem_bar.rect = mem_bar_rect;
			mem_bar.text = QString::number(mem_bar.progress) + "%";
			mem_bar.textVisible = true;
			QApplication::style()->drawControl(QStyle::CE_ProgressBar, &mem_bar, painter);
		//}
	}
	else {
		QStyledItemDelegate::paint(painter, option, index);
	}
}


代理实现类汇总CustomDelegate.h

#pragma once

#include <QObject>
#include <QItemDelegate>
#include <QLineEdit>
#include <QComboBox>
#include <QCheckBox>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QList>
#include <QApplication>
#include <QStyledItemDelegate>

#include <QHeaderView>

#include <QMouseEvent>
#include <QPainter>

#include <QStandardItemModel>

// ComboBox委托
class ComboBoxDelegate :public QItemDelegate
{
	Q_OBJECT

public:
	ComboBoxDelegate(QObject* parent = 0) :QItemDelegate(parent)
	{

	}
	// 开始编辑状态
	QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		QComboBox* editor = new QComboBox(parent);
		//if (flag == false)
		//{
		//	return editor;
		//}
		if (m_list.isEmpty())
			return NULL;
		QStandardItemModel* model = new QStandardItemModel(editor);
		for (int i = 0; i < m_list.count(); i++)
		{
			QStandardItem* item = new QStandardItem(m_list.at(i));
			item->setTextAlignment(Qt::AlignCenter);
			item->setToolTip(ip_list.at(i));
			item->setData(ip_list.at(i), Qt::UserRole);
			model->setItem(i, item);
		}
		editor->setModel(model);
		//editor->setCurrentIndex(0);
		editor->setCurrentText(index.data(Qt::EditRole).toString());
		return editor;
	}
	// 正在编辑状态
	void setEditorData(QWidget* editor, const QModelIndex& index)const
	{
		QString text = index.model()->data(index, Qt::EditRole).toString();
		QComboBox* comboBox = static_cast<QComboBox*>(editor);
		connect(comboBox, &QComboBox::currentTextChanged, this, [=](const QString& text) {
			// 用于置脏数据来着 可以根据需求灵活修改
			//emit ComboTextChanged(index, text);
			});
		comboBox->setCurrentText(text);
	}
	// 退出编辑状态
	void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
	{
		//if (flag == false)
		//	return;
		QComboBox* comboBox = static_cast<QComboBox*>(editor);
		QString text = comboBox->currentText();
		QString ip;
		QStandardItemModel* comb_model = dynamic_cast<QStandardItemModel*>(comboBox->model());
		if (comb_model)
		{
			QStandardItem* item = comb_model->item(comboBox->currentIndex());
			ip = item->data(Qt::UserRole).toString();
		}
		if (text != index.data().toString()) {
			//model->blockSignals(true);
			model->setData(index, ip, Qt::UserRole);
			model->setData(index, text, Qt::EditRole);
			//model->setData(index, "", Qt::UserRole+1);
			//model->blockSignals(false);
		}
		//emit ComboTextChanged(index, text);
		//emit sigStudentSeatChange();

	}
	void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		editor->setGeometry(option.rect);
	}
	// 参数数量可以根据需求灵活修改
	void setMenuList(QStringList _site_name_list, QStringList _site_ip_list)
	{
		m_list = _site_name_list;
		ip_list = _site_ip_list;
	}
	// 	void setSignalFlag(bool _flag)
	// 	{
	// 		flag = _flag;
	// 	}

signals:
	// 可以根据需求添加自定义信号进行处理
	//void ComboTextChanged(const QModelIndex& index, const QString text)const;
	//void sigStudentSeatChange(const QTableWidgetItem * _item)const;
private:
	QStringList m_list;
	QStringList ip_list;
	//bool flag;		// true为可编辑状体 false为不可编辑状态
};

// 状态代理
class StatusDelegate : public QStyledItemDelegate
{
	Q_OBJECT
public:
	StatusDelegate(QObject* parent = nullptr) {};
	~StatusDelegate() {}
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:
	QString m_text;
};

//只读代理
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 nullptr;
	}
};

//spinBox委托
class SpinBoxDelegate
	: public QItemDelegate
{
	Q_OBJECT
public:
	SpinBoxDelegate(QObject* parent = 0) :QItemDelegate(parent) { m_minimum = 0; m_maxinum = 0; m_singleStep = 0; }
	QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		QSpinBox* editor = new QSpinBox(parent);
		editor->setMinimum(m_minimum);
		editor->setMaximum(m_maxinum);
		editor->setSingleStep(m_singleStep);
		return editor;
	}

	void setEditorData(QWidget* editor, const QModelIndex& index)const
	{
		int value = index.model()->data(index, Qt::EditRole).toInt();
		QSpinBox* spinbox = static_cast<QSpinBox*>(editor);
		// 此处注释部分为Qt5实现方法 为了解决函数重载的信号绑定问题 Qt升级后将函数重载的函数更改了名字如下所示
		connect(spinbox, /*static_cast<void (QSpinBox::*)(const QString&)>*/(&QSpinBox::/*valueChanged*/textChanged), this, [=](const QString& value)
			{
				emit SpinBoxValueChanged(index, value);
			});
		spinbox->setValue(value);
	}
	void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
	{
		QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
		int value = spinBox->value();
		if (model->data(index, Qt::EditRole).toInt() != value)
			model->setData(index, value, Qt::EditRole);
	}

	void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		editor->setGeometry(option.rect);
	}

	void setSpinBoxProperty(double minimum, double maxinum, double singleStep)
	{
		m_minimum = (int)minimum;
		m_maxinum = (int)maxinum;
		m_singleStep = (int)singleStep;
	}

signals:
	void SpinBoxValueChanged(const QModelIndex& index, const QString& value)const;

private:
	int m_minimum;		// 最小值
	int m_maxinum;		// 最大值
	int m_singleStep;	// 每步调整大小
};

// DoubleSpinBox委托
class DoubleSpinBoxDelegate
	: public QItemDelegate
{
	Q_OBJECT
public:
	DoubleSpinBoxDelegate(QObject* parent = 0) :QItemDelegate(parent) { m_minimum = 0; m_maxinum = 0; m_singleStep = 0; m_decimals = 0; }
	QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		QDoubleSpinBox* editor = new QDoubleSpinBox(parent);
		editor->setMinimum(m_minimum);
		editor->setMaximum(m_maxinum);
		editor->setSingleStep(m_singleStep);
		editor->setDecimals(m_decimals);
		return editor;
	}
	void setEditorData(QWidget* editor, const QModelIndex& index)const
	{
		double value = index.model()->data(index, Qt::EditRole).toDouble();
		QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
		// 此处注释部分为Qt5实现方法 为了解决函数重载的信号绑定问题 Qt升级后将函数重载的函数更改了名字如下所示
		connect(doubleSpinBox, /*static_cast<void (QDoubleSpinBox::*)(const QString&)>*/(&QDoubleSpinBox::textChanged/*valueChanged*/), this, [=](const QString& value)
			{
				emit DoubleSpinBoxValueChanged(index, value);
			});
		doubleSpinBox->setValue(value);
	}
	void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
	{
		QDoubleSpinBox* doubleSpinBox = static_cast<QDoubleSpinBox*>(editor);
		double value = doubleSpinBox->value();
		if (model->data(index, Qt::EditRole).toDouble() != value)
			model->setData(index, QString::number(value, 'f', m_decimals), Qt::EditRole);
	}
	void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
	{
		editor->setGeometry(option.rect);
	}

	void setDoubleSpinBoxProperty(double minimum, double maxinum, double singleStep, int decimals)
	{
		m_minimum = minimum;
		m_maxinum = maxinum;
		m_singleStep = singleStep;	// 每步调整多少
		m_decimals = decimals;	// 小数点后几位
	}

signals:
	void DoubleSpinBoxValueChanged(const QModelIndex& index, const QString& value)const;

private:
	double m_minimum;
	double m_maxinum;
	double m_singleStep;
	int m_decimals;
};

// checkBox勾选框代理
class CheckBoxDelegate :public QStyledItemDelegate
{
	Q_OBJECT
public:
	CheckBoxDelegate(QObject* parent = 0) {}
protected:
	virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;
	virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const;
	virtual bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);

signals:
	void CheckStateChanged(const QModelIndex& _index, int _state);
};

//	表头添加checkBox
class CCheckBoxHeaderView : public QHeaderView
{
	Q_OBJECT
public:
	CCheckBoxHeaderView(int checkBoxColumnID, Qt::Orientation orientation, QWidget* parent);
	~CCheckBoxHeaderView() {}
	void setChecked(bool ischeck)
	{
		m_checkBoxIsOn = ischeck;
		updateSection(m_checkBoxColumnId);
	}

	void setSorted(bool isSort)
	{
		m_isSort = isSort;
	}

protected:
	void mousePressEvent(QMouseEvent* event);
	void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const;

signals:
	void sig_AllChecked(bool);

private:
	int m_checkBoxColumnId;
	bool m_checkBoxIsOn;
	bool m_isSort;
};

//	pushButton代理
class PushbuttonDelegate : public QItemDelegate
{
	Q_OBJECT
public:
	PushbuttonDelegate(QObject* parent = 0) {}
	~PushbuttonDelegate() {}

protected:
	void paint(QPainter* painter, const QStyleOptionViewItem& option,
		const QModelIndex& index) const;

	bool editorEvent(QEvent* event, QAbstractItemModel* model,
		const QStyleOptionViewItem& option, const QModelIndex& index);
public:
	void setText(const QString& text);

signals:
	void sig_buttonClicked(const QModelIndex& index, const QRect& rect);

private:
	QMap<QModelIndex, QStyleOptionButton*>m_pBtns;
	QString m_text;
};

// 自定义组件
#include <QPushButton>
#include <QFileDialog>
#include <QHBoxLayout>
#include <QObject>
class  CustomWidget
	:public QWidget
{
	Q_OBJECT
public:
	explicit CustomWidget(QWidget* parent = 0);
	~CustomWidget();
public:
	void SetText(QString _text);
	QString GetText();
private slots:
	void SlotButtonclicked();
private:
	QLineEdit* le_path_;
	QPushButton* pb_open_;
	QString exe_path_;
	QHBoxLayout* main_layout_;
};

// 自定义组合代理LineEdit+pushButton
// 结合上面类进行使用 先创建qwidget再把widget放进代理类
class CustomComDelegate
	: public QItemDelegate
{
	Q_OBJECT
public:
	CustomComDelegate(QObject* parent = nullptr);
	~CustomComDelegate();

signals:
	void SignalExePath(const QModelIndex _index, QString _exe_path) const;

protected:
	virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;

	virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const;

	virtual QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const;

	virtual void setEditorData(QWidget* editor, const QModelIndex& index) const;

	virtual void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const;

};

// 双进度条代理
class ProgressBarDelegate
	:public QStyledItemDelegate
{
	Q_OBJECT
public:
	ProgressBarDelegate(QObject* parent = nullptr);
	~ProgressBarDelegate();

protected:
	virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;

};

代理实现类CustomDelegate.cpp

#include "CustomDelegate.h"

void StatusDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	const bool enabled = option.state & QStyle::State_Enabled;
	const bool active = option.state & QStyle::State_Active;
	const bool selected = option.state & QStyle::State_Selected;

	if (enabled && active && selected)
		painter->fillRect(option.rect, option.palette.highlight());
	if (enabled && selected && !active) {
		painter->fillRect(option.rect, option.palette.color(QPalette::Inactive, QPalette::Highlight));
	}

	int height = option.rect.height();
	int width = option.rect.width();
	int m_x = option.rect.x() + width / 4 - 5;
	int m_y = option.rect.y() + height / 2 - 5;

	QString site_status = index.data(Qt::UserRole).toString();

	painter->save();
	//QColor brush = Qt::transparent;
	if (index.data(Qt::UserRole).toString() == "关于")
	{
		//brush = QColor(6, 176, 37);
		QPixmap pixmap = QPixmap(8, 8);
		pixmap.load(QString(":/QtDelegateTest/res/关于.png"));
		painter->drawPixmap(m_x - 10, m_y, pixmap);
		painter->drawText(m_x, option.rect.y(), width * 3 / 4, height, Qt::AlignCenter, site_status);
	}
	else if (index.data(Qt::UserRole).toString() == "设置")
	{
		//brush = QColor(177, 177, 177);
		QPixmap pixmap = QPixmap(8, 8);
		pixmap.load(QString(":/QtDelegateTest/res/设置.png"));
		painter->drawPixmap(m_x - 10, m_y, pixmap);
		painter->drawText(m_x, option.rect.y(), width * 3 / 4, height, Qt::AlignCenter, site_status);
	}
	else if (index.data(Qt::UserRole).toString() == "退出")
	{
		//brush = QColor(255, 0, 0);
		QPixmap pixmap = QPixmap(8, 8);
		pixmap.load(QString(":/QtDelegateTest/res/退出.png"));
		painter->drawPixmap(m_x - 10, m_y, pixmap);
		painter->drawText(m_x, option.rect.y(), width * 3 / 4, height, Qt::AlignCenter, site_status);
	}
	painter->restore();
}

bool StatusDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
	return QStyledItemDelegate::editorEvent(event, model, option, index);
}

static QRect CheckBoxRect(const QStyleOptionViewItem& viewItemStyleOptions)
{
	QStyleOptionButton checkBoxStyleOption;
	QRect checkBoxRect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkBoxStyleOption);
	QPoint checkBoxPoint(viewItemStyleOptions.rect.x() + viewItemStyleOptions.rect.width() / 2 - checkBoxRect.width() / 2,
		viewItemStyleOptions.rect.y() + viewItemStyleOptions.rect.height() / 2 - checkBoxRect.height() / 2);
	return QRect(checkBoxPoint, checkBoxRect.size());
}

QSize CheckBoxDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	QStyleOptionViewItem opt = option;
	QSize opt_size = QStyledItemDelegate::sizeHint(option, index);
	return QSize(40,opt_size.height());
}

void CheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	//const bool enabled = option.state & QStyle::State_Enabled;
	//const bool active = option.state & QStyle::State_Active;
	//const bool selected = option.state & QStyle::State_Selected;

	 绘制原生背景
	//if (enabled && active && selected)
	//	painter->fillRect(option.rect, option.palette.highlight());
	//if (enabled && selected && !active)
	//	painter->fillRect(option.rect, option.palette.color(QPalette::Inactive, QPalette::Highlight));

	QStyleOptionViewItem opt = option;
 	bool checked = index.model()->data(index, Qt::DisplayRole).toBool();
	QStyleOptionButton checkBoxStyleOption;
	checkBoxStyleOption.state |= QStyle::State_Enabled;
	checkBoxStyleOption.state |= checked ? QStyle::State_On : QStyle::State_Off;
	checkBoxStyleOption.rect = CheckBoxRect(opt);
	painter->setPen(Qt::black);
	QRect text_rect = CheckBoxRect(opt);
	text_rect.setWidth(text_rect.width() + 20);
	painter->drawText(text_rect, Qt::AlignRight | Qt::AlignVCenter, QString::number(index.row() + 1));

	QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxStyleOption, painter);
}

bool CheckBoxDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
	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();
	if (checked == false)
		emit CheckStateChanged(index, 1);
	else
		emit CheckStateChanged(index, 0);
	return model->setData(index, !checked, Qt::EditRole);
}

CCheckBoxHeaderView::CCheckBoxHeaderView(int checkBoxColumnId, Qt::Orientation orientation, QWidget* parent)
	: QHeaderView(orientation, parent)
{
	m_checkBoxColumnId = checkBoxColumnId;
	m_checkBoxIsOn = false;
	m_isSort = false;
}

void CCheckBoxHeaderView::paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const
{
	painter->save();
	QHeaderView::paintSection(painter, rect, logicalIndex);
	
	painter->restore();
	if (logicalIndex == m_checkBoxColumnId)
	{
		QStyleOptionButton option;
		int width = 3;
		for (int i = 0; i < logicalIndex; ++i)
			width += sectionSize(i);
		option.rect = QRect(width, 5, 15, 15);
		if (m_checkBoxIsOn)
			option.state = QStyle::State_On;
		else
			option.state = QStyle::State_Off;
		this->style()->drawControl(QStyle::CE_CheckBox, &option, painter);
	}
}

void CCheckBoxHeaderView::mousePressEvent(QMouseEvent* event)
{
	int x = event->pos().x();
	int y = event->pos().y();
	if (visualIndexAt(event->pos().x()) == m_checkBoxColumnId)
	{
		//if (event->pos().x() >= 3 && event->pos().x() <= 18 && event->pos().y() >= 5 && event->pos().y() <= 20)
		{
			this->setSectionsClickable(true);
			if (m_checkBoxIsOn)
				m_checkBoxIsOn = false;
			else
				m_checkBoxIsOn = true;
			this->updateSection(m_checkBoxColumnId);
			// 可以连接这个信号将下面所有checkbox状态改变
			emit sig_AllChecked(m_checkBoxIsOn);
		}
		//else
		//{
		//	this->setSectionsClickable(m_isSort);
		//}
	}
	else
	{
		this->setSectionsClickable(m_isSort);
	}
	QHeaderView::mousePressEvent(event);
}

void PushbuttonDelegate::setText(const QString& text)
{
	m_text = text;
}

void PushbuttonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
	const QModelIndex& index) const
{
	const bool enabled = option.state & QStyle::State_Enabled;
	const bool active = option.state & QStyle::State_Active;
	const bool selected = option.state & QStyle::State_Selected;

	QStyleOptionButton button;
	button.rect = option.rect.adjusted(6, 6, -6, -6);
	button.text = m_text;
	button.state = option.state;
	button.iconSize = QSize(18, 18);
	QPixmap pixmap = QPixmap(8, 8);
	pixmap.load(QString(":/QtDelegateTest/res/设置.png"));
	button.icon = QIcon(pixmap);

	//! \获取按钮状态
	bool pressed = index.data(Qt::UserRole + 2).toBool();
	button.state |= pressed ? QStyle::State_Sunken : QStyle::State_Raised;

	if (enabled && active && selected)
		painter->fillRect(option.rect, option.palette.highlight());
	if (enabled && selected && !active) {
		painter->fillRect(option.rect, option.palette.color(QPalette::Inactive, QPalette::Highlight));
	}
	button.palette.setColor(QPalette::All, QPalette::ButtonText, painter->pen().color());
	QApplication::style()->drawControl(QStyle::CE_PushButton, &button, painter);
}

bool PushbuttonDelegate::editorEvent(QEvent* event, QAbstractItemModel* model,
	const QStyleOptionViewItem& option, const QModelIndex& index)
{
	if (event->type() == QEvent::MouseButtonPress || event->type() == QEvent::MouseButtonRelease) {
		if (QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event)) {
			if (mouseEvent->button() == Qt::LeftButton) {
				bool pressed = false;
				(event->type() == QEvent::MouseButtonPress) ? pressed = true : pressed = false;
				model->setData(index, pressed, /*Button_State_Sunken*/Qt::UserRole + 2);
				if (event->type() == QEvent::MouseButtonPress) {
					/*	QString base_type = model->data(model->index(index.row(), index.column() - 2)).toString();*/
					QStyleOption option_base = option;
					QRect rect = option_base.rect;
					emit sig_buttonClicked(index, rect);
				}
				return true;
			}
		}
	}
	return true;
}

// 自定义组合代理
CustomWidget::CustomWidget(QWidget* parent /*= 0*/)
	:QWidget(parent)
	, exe_path_()
{
	pb_open_ = new QPushButton("...");
	pb_open_->setFixedSize(25, 25);
	le_path_ = new QLineEdit();
	// 设置不可编辑
	le_path_->setEnabled(true);

	main_layout_ = new QHBoxLayout();
	main_layout_->addWidget(le_path_);
	main_layout_->addWidget(pb_open_);
	main_layout_->setContentsMargins(0, 0, 0, 0);
	main_layout_->setSpacing(0);
	this->setLayout(main_layout_);

	connect(pb_open_, &QPushButton::clicked, this, &CustomWidget::SlotButtonclicked);
}

CustomWidget::~CustomWidget()
{

}

void CustomWidget::SlotButtonclicked()
{
	QString exe_path = le_path_->text();
	if (exe_path.isEmpty()) {
		exe_path = QFileDialog::getOpenFileName(this, "选择应用程序路径", "C:/Users/admin/Desktop/", "应用程序(*.exe)");
	}
	else {
		exe_path = QFileDialog::getOpenFileName(this, "选择应用程序路径", exe_path, "应用程序(*.exe)");
	}
	if (!exe_path.isEmpty()) {
		le_path_->setText(exe_path);
	}
}

void CustomWidget::SetText(QString _text)
{
	le_path_->setText(_text);
}

QString CustomWidget::GetText()
{
	return le_path_->text();
}

// 自定义组合代理
CustomComDelegate::CustomComDelegate(QObject* parent /*= nullptr*/)
	:QItemDelegate(parent)
{

}

CustomComDelegate::~CustomComDelegate()
{

}

void CustomComDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	QItemDelegate::paint(painter, option, index);
}

QSize CustomComDelegate::sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	return QItemDelegate::sizeHint(option, index);
}

QWidget* CustomComDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	CustomWidget* custom_widget = new CustomWidget(parent);
	custom_widget->installEventFilter(const_cast<CustomComDelegate*>(this));
	return custom_widget;
}

void CustomComDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
	QString value = index.model()->data(index, Qt::DisplayRole).toString();
	CustomWidget* custom_widget = qobject_cast<CustomWidget*>(editor);
	if (!value.isEmpty()) {
		custom_widget->SetText(value);
	}
	else {
		QItemDelegate::setEditorData(editor, index);
	}
}

void CustomComDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
	CustomWidget* custom_widget = qobject_cast<CustomWidget*>(editor);
	// 	if (custom_widget->GetText().isEmpty()){
	// 		model->setData(index, "");
	// 	}
	// 	else{
	model->setData(index, custom_widget->GetText());
	emit SignalExePath(index, custom_widget->GetText());
	//}
}

#include <QStyleOptionProgressBar>

ProgressBarDelegate::ProgressBarDelegate(QObject* parent /*= nullptr*/)
{

}

ProgressBarDelegate::~ProgressBarDelegate()
{

}

void ProgressBarDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	if (index.isValid()) {
		QRect rect = option.rect;
		int m_x = option.rect.x();
		int m_y = option.rect.y();

		// 0是cpu 1是gpu
		//int flag = index.data(Qt::UserRole + 1).toInt();
		//if (flag == 0)
		//{
			// 图标
			QPixmap cpu_pixmap = QPixmap(8, 8);
			cpu_pixmap.load(QString(":/QtDelegateTest/res/CPU.png"));
			painter->drawPixmap(m_x + 5, m_y + 7, cpu_pixmap);
			// CPU进度条
			QStyleOptionProgressBar cpu_bar;
			QRect cpu_bar_rect;
			cpu_bar_rect.setRect(rect.left() + 30, rect.top(), rect.width() - 30, rect.height()/2 - 2);
			cpu_bar.rect = cpu_bar_rect;

			cpu_bar.progress = index.data(Qt::UserRole).toInt();
			cpu_bar.maximum = 100;
			cpu_bar.minimum = 0;
			cpu_bar.textAlignment = Qt::AlignCenter;
			cpu_bar.text = QString::number(cpu_bar.progress) + "%";
			cpu_bar.textVisible = true;
			QApplication::style()->drawControl(QStyle::CE_ProgressBar, &cpu_bar, painter);
		//}
		//else if (flag == 1)
		//{
			QPixmap mem_pixmap = QPixmap(8, 8);
			mem_pixmap.load(QString(":/QtDelegateTest/res/内存.png"));
			painter->drawPixmap(m_x + 5, m_y+option.rect.height()/2 + 7, mem_pixmap);

			// 内存进度条
			QStyleOptionProgressBar mem_bar;
			QRect mem_bar_rect;
			mem_bar_rect.setRect(rect.left() + 30, rect.top()+ rect.height() / 2 + 2, rect.width() - 30, rect.height()/2 - 4);

			mem_bar.progress = index.data(Qt::UserRole+1).toInt();
			mem_bar.maximum = 100;
			mem_bar.minimum = 0;
			mem_bar.textAlignment = Qt::AlignCenter;
			mem_bar.rect = mem_bar_rect;
			mem_bar.text = QString::number(mem_bar.progress) + "%";
			mem_bar.textVisible = true;
			QApplication::style()->drawControl(QStyle::CE_ProgressBar, &mem_bar, painter);
		//}
	}
	else {
		QStyledItemDelegate::paint(painter, option, index);
	}
}


使用代理类QtDelegateTest.h

#pragma once

#include <QtWidgets/QMainWindow>
#include <QObject>
#include "ui_QtDelegateTest.h"
#include "CustomDelegate.h"

class QtDelegateTest : public QMainWindow
{
    Q_OBJECT

public:
    QtDelegateTest(QWidget *parent = Q_NULLPTR);

private:
    Ui::QtDelegateTestClass ui;

    // combobox测试
    void ComboboxTest();

    // 状态测试
    void StatusTest();

    // 只读代理测试
    void ReadOnlyTest();

    // spinBox委托
    void SpinBoxDelegateTest();

    // DoubleSpinBox委托
    void DoubleBoxDelegateTest();

    // checkBox勾选框代理
    void CheckBoxDelegateTest();

    //	表头添加checkBox
    void CCheckBoxHeaderViewTest();

    // 设置所有checkbox状态
    void SlotAllCheckboxStatus(bool _flag);

    // pushButton代理
    void PushbuttonDelegateTest();

    // 自定义组件
    void CustomWidgetTest();

    // 存放exe路径
    void SlotSetExePath(const QModelIndex _index, QString _exe_path);

    // 双进度条测试
    void ProgressBarDelegateTest();

    ComboBoxDelegate* combobox_delegate;    // combobox测试
    SpinBoxDelegate* spin_box_delegate;     // spinBox委托
    DoubleSpinBoxDelegate* double_spin_box; // DoubleSpinBox委托
    CCheckBoxHeaderView* ccheck_box_header; // 表头添加checkBox
};

使用代理类QtDelegateTest.cpp

#include "QtDelegateTest.h"

QtDelegateTest::QtDelegateTest(QWidget* parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	ComboboxTest();
	StatusTest();
	ReadOnlyTest();
	SpinBoxDelegateTest();
	DoubleBoxDelegateTest();
	CheckBoxDelegateTest();
	CCheckBoxHeaderViewTest();
	PushbuttonDelegateTest();
	CustomWidgetTest();
	ProgressBarDelegateTest();
}

void QtDelegateTest::ComboboxTest()
{
	combobox_delegate = new ComboBoxDelegate;
	ui.delegate_tableWidget->setItemDelegateForColumn(0, combobox_delegate);

	QStringList name;
	name.append("1");
	name.append("2");

	QStringList data;
	data.append("一");
	data.append("二");

	combobox_delegate->setMenuList(name, data);
}

void QtDelegateTest::StatusTest()
{
	ui.delegate_tableWidget->setItemDelegateForColumn(1, new StatusDelegate);
	QTableWidgetItem* item = ui.delegate_tableWidget->item(0, 1);
	item->setData(Qt::UserRole, "关于");
	// 设置只读的一种方式
	item->setFlags(Qt::ItemIsEnabled);
	item = ui.delegate_tableWidget->item(1, 1);
	item->setData(Qt::UserRole, "设置");
	item->setFlags(Qt::ItemIsEnabled);
	item = ui.delegate_tableWidget->item(2, 1);
	item->setData(Qt::UserRole, "退出");
	item->setFlags(Qt::ItemIsEnabled);
}

void QtDelegateTest::ReadOnlyTest()
{
	ui.delegate_tableWidget->setItemDelegateForColumn(2, new ReadOnlyDelegate);
}

void QtDelegateTest::SpinBoxDelegateTest()
{
	spin_box_delegate = new SpinBoxDelegate;
	spin_box_delegate->setSpinBoxProperty(0,1000,2);
	ui.delegate_tableWidget->setItemDelegateForColumn(3, spin_box_delegate);
}

void QtDelegateTest::DoubleBoxDelegateTest()
{
	double_spin_box = new DoubleSpinBoxDelegate;
	double_spin_box->setDoubleSpinBoxProperty(0, 1000, 0.01, 5);
	ui.delegate_tableWidget->setItemDelegateForColumn(4, double_spin_box);
}

void QtDelegateTest::CheckBoxDelegateTest()
{
	ui.delegate_tableWidget->setItemDelegateForColumn(5, new CheckBoxDelegate);
}

void QtDelegateTest::CCheckBoxHeaderViewTest()
{
	ccheck_box_header = new CCheckBoxHeaderView(5, Qt::Horizontal, ui.delegate_tableWidget);
	ui.delegate_tableWidget->setHorizontalHeader(ccheck_box_header);
	connect(ccheck_box_header, &CCheckBoxHeaderView::sig_AllChecked, this, &QtDelegateTest::SlotAllCheckboxStatus);
}

void QtDelegateTest::SlotAllCheckboxStatus(bool _flag)
{
	int rowCount = ui.delegate_tableWidget->rowCount();
	for (int i = 0; i < rowCount; ++i) {
		QTableWidgetItem* item = ui.delegate_tableWidget->item(i, 5);
		item->setData(Qt::DisplayRole, _flag);
	}
}

void QtDelegateTest::PushbuttonDelegateTest()
{
	PushbuttonDelegate* pushbutton_delegate = new PushbuttonDelegate;
	pushbutton_delegate->setText("设置");
	ui.delegate_tableWidget->setItemDelegateForColumn(6, pushbutton_delegate);

}

void QtDelegateTest::CustomWidgetTest()
{
	CustomComDelegate* custom = new CustomComDelegate;
	ui.delegate_tableWidget->setItemDelegateForColumn(7, custom);
	connect(custom, &CustomComDelegate::SignalExePath, this, &QtDelegateTest::SlotSetExePath);
}

void QtDelegateTest::SlotSetExePath(const QModelIndex _index, QString _exe_path)
{
	QFileInfo info(_exe_path);
	QString name = info.fileName();
	QString exe_name = name.replace(".exe", "");
	ui.delegate_tableWidget->item(_index.row(), _index.column() - 1)->setData(Qt::DisplayRole, exe_name);
}

void QtDelegateTest::ProgressBarDelegateTest()
{
	ui.delegate_tableWidget->setItemDelegateForColumn(8, new ProgressBarDelegate);

	ui.delegate_tableWidget->item(0, 8)->setData(Qt::UserRole, 80);
	ui.delegate_tableWidget->item(0, 8)->setData(Qt::UserRole+1, 70);
	ui.delegate_tableWidget->item(1, 8)->setData(Qt::UserRole , 70);
	ui.delegate_tableWidget->item(1, 8)->setData(Qt::UserRole + 1, 60);
	ui.delegate_tableWidget->item(2, 8)->setData(Qt::UserRole, 70);
	ui.delegate_tableWidget->item(2, 8)->setData(Qt::UserRole + 1, 60);
}

  • 13
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奇树谦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值