参考:
QTableView表格控件代理详解
https://blog.csdn.net/u010031316/article/details/120366295
文章目录
运行环境:WIN10,VS2022,QT6.3
创建的QtWidgetApplication项目,解决方案目录及main主函数如下图:
![VS](https://i-blog.csdnimg.cn/blog_migrate/27e70569df7bcde9cac7ad6d1ffea05c.png#pic_center)
qrc资源文件中就放了几个从 阿里巴巴矢量图库下载的几张图:
![qrc](https://i-blog.csdnimg.cn/blog_migrate/3e21e8612c6a061ef015e8e822833eca.png#pic_center)
ui中就部署了一个qtablewidget,如图所示:
分模块代码
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);
}