自定义委托
代理就是在视图组件上为编辑数据提供的临时编辑器,例如在 QTableView 组件上编辑一个单元格的数据时,默认会提供一个 QLineEdit 编辑框。代理负责从模型获取相应的数据,然后将其显示在编辑器里,修改数据后又将编辑器里的数据保存到模型中 。
以下是对QPushButton
、QComboxBox
、QLineEdit
、QCheckBox
的示例。
QWControlDelegate.h
#pragma once
#include <QStyledItemDelegate>
#include <QItemDelegate>
#include <QObject>
#include <QPushButton>
#include <QCheckBox>
#include <QLineEdit>
#include <QSpinBox>
#include <QComboBox>
#include <QMessageBox>
#include <QMouseEvent>
#include <QApplication>
#include <QPainter>
#include <QStyleOption>
#include <QDesktopWidget>
#include <QToolTip>
#include <QDebug>
#include <QMessageBox>
#include <QListWidget>
#include <QTableWidget>
/*QWPushButtonDelegate*/
class QWPushButtonDelegate : public QStyledItemDelegate
{
public:
Q_OBJECT
public:
void setItems(QStringList items);//初始化设置列表内容
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);
signals:
void edit1st(const QModelIndex& index);
void edit2nd(const QModelIndex& index);
private:
QPoint m_mousePoint;//鼠标位置
int m_nType;//按钮状态:0-划过,1-按下
QStringList m_btnNames;
};
/*QWComboBoxDelegate*/
class QWComboBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
void setItems(QStringList items, bool isEdit);//初始化设置列表内容
//创建编辑器
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
//设置编辑器数据
void setEditorData(QWidget* editor, const QModelIndex& index)const Q_DECL_OVERRIDE;
//更新编辑器集合属性
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const Q_DECL_OVERRIDE;
//设置模型数据
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const;
private:
QStringList m_ItemList;//选择列表
bool m_isEdit;//是否可编辑
};
/*QWCheckBoxDelegate*/
class QWCheckBoxDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
/*QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
void setEditorData(QWidget* editor, const QModelIndex& index)const Q_DECL_OVERRIDE;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;*/
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
bool editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index);
};
/*QWLineEditDelegate*/
class QWLineEditDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
QWLineEditDelegate(QObject *parent = NULL);
~QWLineEditDelegate();
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
void setEditorData(QWidget* editor, const QModelIndex& index)const Q_DECL_OVERRIDE;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const;
};
/*QWIntSpinDelegate*/
class QWIntSpinDelegate : public QStyledItemDelegate
{
Q_OBJECT
public:
//QWIntSpinDelegate(QObject* parent = 0);
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
void setEditorData(QWidget* editor, const QModelIndex& index)const Q_DECL_OVERRIDE;
void setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const Q_DECL_OVERRIDE;
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const;
};
/*QWLineEditDelegate_IP*/
//继承QWLineEditDelegate并重写QWLineEditDelegate_IP
class QWLineEditDelegate_IP : public QWLineEditDelegate
{
Q_OBJECT
public:
QWidget* createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index)
const Q_DECL_OVERRIDE;
void setEditorData(QWidget* editor, const QModelIndex& index)const Q_DECL_OVERRIDE;
};
QWControlDelegate.cpp
#include "QWControlDelegate.h"
#pragma execution_character_set("utf-8")
//QWPushButtonDelegate***************************************************************************************************************
void QWPushButtonDelegate::setItems(QStringList items)
{
m_btnNames = items;
}
//绘制按钮
void QWPushButtonDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
QStyleOptionViewItem viewOption(option);
initStyleOption(&viewOption, index);
if (option.state.testFlag(QStyle::State_HasFocus))
viewOption.state = viewOption.state^QStyle::State_HasFocus;
QStyledItemDelegate::paint(painter, viewOption, index);
//计算按钮显示区域
int nCount = m_btnNames.count();
int w = nCount != 0 ? option.rect.width() / nCount : 0;
if (w < 0)
return;
for (int i = 0; i < nCount; i++)
{
//绘制按钮
QStyleOptionButton button;
button.rect = option.rect.adjusted(4 + i*w, 4, -(w*(nCount - i - 1) + 4), -4);
button.text = m_btnNames.at(i);
button.state |= QStyle::State_Enabled;
if (button.rect.contains(m_mousePoint))
if (m_nType == 0)
button.state |= QStyle::State_MouseOver;
else if (m_nType == 1)
button.state |= QStyle::State_Sunken;
QPushButton pushBtn;
pushBtn.setStyleSheet("background-color:#072433;");
pushBtn.style()->drawControl(QStyle::CE_PushButton, &button, painter, &pushBtn);
}
}
//响应按钮事件 - 划过、按下
bool QWPushButtonDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
m_nType = -1;
bool bRepaint = false;
QMouseEvent* pEvent = static_cast<QMouseEvent*>(event);
m_mousePoint = pEvent->pos();
int nCount = m_btnNames.count();
int w = nCount != 0 ? option.rect.width() / nCount : 0;
if (w < 0) {
return false;
}
//还原鼠标样式
//QApplication::restoreOverrideCursor();
for (int i = 0; i < nCount; ++i)
{
QStyleOptionButton button;
button.rect = option.rect.adjusted(4 + i*w, 4, -(w*(nCount - i - 1) + 4), -4);
//鼠标位于按钮之上
if (!button.rect.contains(m_mousePoint))
continue;
bRepaint = true;
switch (event->type())
{
//鼠标划过
case QEvent::MouseMove:
{
//设置鼠标样式为手型
//QApplication::setOverrideCursor(Qt::PointingHandCursor);
m_nType = 0;
//QToolTip::showText(pEvent->globalPos(), m_btnNames.at(i));
break;
}
//鼠标按下
case QEvent::MouseButtonPress:
{
m_nType = 1;
break;
}
//鼠标释放
case QEvent::MouseButtonRelease:
{
switch (i)
{
case 0:
{
emit edit1st(index);
break;
}
case 1:
{
emit edit2nd(index);
break;
}
default:
break;
}
}
default:
break;
}
}
return bRepaint;
}
//QWComboBoxDelegate********************************************************************************************************************
void QWComboBoxDelegate::setItems(QStringList items, bool isEdit)
{
m_ItemList = items;
m_isEdit = isEdit;
}
QWidget* QWComboBoxDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
Q_UNUSED(option);
Q_UNUSED(index);
//创建需要的控件进行返回
QComboBox* editor = new QComboBox(parent);
editor->setFrame(false);//设置为无边框
for (int i = 0; i < m_ItemList.count(); i++) //从字符串列表初始下拉列表
{
editor->addItem(m_ItemList.at(i));
}
editor->setEditable(m_isEdit);//是否可编辑
return editor;
}
void QWComboBoxDelegate::setEditorData(QWidget* editor, const QModelIndex& index)const
{
QString text = index.model()->data(index, Qt::EditRole).toString();
QComboBox* comboBox = static_cast<QComboBox*>(editor);
int tindex = comboBox->findText(text);//通过显示文本内容得到当前的item
comboBox->setCurrentIndex(tindex);
}
void QWComboBoxDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
{
QComboBox* comboBox = static_cast<QComboBox*>(editor);
QString text = comboBox->currentText();//通过当前的索引得到文本内容
model->setData(index, text, Qt::EditRole);
}
void QWComboBoxDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
//Q_UNUSED(index);
editor->setGeometry(option.rect);//外观尺寸
}
void QWComboBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
QStyleOptionViewItem newoption(option);
newoption.displayAlignment = Qt::AlignCenter;
QStyledItemDelegate::paint(painter, newoption, index);
}
//QWCheckBoxDelegate****************************************************************************************************************
static QRect CheckBoxRect(const QStyleOptionViewItem& viewItemStyleOptions)
{
//绘制按钮所需要的参数
QStyleOptionButton checkBoxStyleOption;
//按照给定的风格参数 返回元素子区域
QRect checkBoxRect = QApplication::style()->subElementRect(QStyle::SE_CheckBoxIndicator, &checkBoxStyleOption);
//返回QCheckBox
QPoint checkBoxPoint(viewItemStyleOptions.rect.x() + viewItemStyleOptions.rect.width() / 2 - checkBoxRect.width() / 2,
viewItemStyleOptions.rect.y() + viewItemStyleOptions.rect.height() / 2 - checkBoxRect.height() / 2);
//返回QCheckBox几何形状
return QRect(checkBoxPoint, checkBoxRect.size());
}
void QWCheckBoxDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
bool checked = index.model()->data(index, Qt::DisplayRole).toBool();
if (index.column() == 2) {
//按钮的风格选项
QStyleOptionButton checkBoxStyleOption;
//|=为复合赋值语句,a|=b等价于a=a|b,对a和b进行位运算或运算
checkBoxStyleOption.state |= QStyle::State_Enabled;
//根据值判断是否选中
checkBoxStyleOption.state |= checked ? QStyle::State_On : QStyle::State_Off;
//返回QCheckBox几何形状
checkBoxStyleOption.rect = CheckBoxRect(option);
QCheckBox checkbtn;
checkbtn.setStyleSheet("background-color:#072433;");
//绘制QCheckBox
QApplication::style()->drawControl(QStyle::CE_CheckBox, &checkBoxStyleOption, painter, &checkbtn);
}
else {
//否则调用默认委托
QStyledItemDelegate::paint(painter, option, index);
}
}
bool QWCheckBoxDelegate::editorEvent(QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index)
{
if (index.column() == 16 | index.column() == 18) {
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();
return model->setData(index, !checked, Qt::EditRole);
}
else {
return QStyledItemDelegate::editorEvent(event, model, option, index);
}
}
//QWLineEditDelegate************************************************************************************************************
QWLineEditDelegate::QWLineEditDelegate(QObject *parent)
: QStyledItemDelegate(parent)
{
}
QWLineEditDelegate::~QWLineEditDelegate()
{
}
QWidget* QWLineEditDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QLineEdit* editor = new QLineEdit(parent);
editor->setFrame(false);
return editor;
}
void QWLineEditDelegate::setEditorData(QWidget* editor, const QModelIndex& index)const
{
QString value = index.model()->data(index, Qt::EditRole).toString();
QLineEdit* le = dynamic_cast<QLineEdit*>(editor);
le->setText(value);
}
void QWLineEditDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
{
model->setData(index, dynamic_cast<QLineEdit*>(editor)->text(), Qt::EditRole);
}
void QWLineEditDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
editor->setGeometry(option.rect);
}
void QWLineEditDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
QStyleOptionViewItem newoption(option);
newoption.displayAlignment = Qt::AlignCenter;
QStyledItemDelegate::paint(painter, newoption, index);
}
void QWLineEditDelegate_IP::setEditorData(QWidget* editor, const QModelIndex& index)const
{
//将model中的数据显示在QTableView中
QString value = index.model()->data(index, Qt::EditRole).toString();
QLineEdit* le = dynamic_cast<QLineEdit*>(editor);
le->setText(value);
qDebug() << le->text();
if(le->text()=="")
le->setText("0.0.0.0");
QStringList IPlist = le->text().split(".");
if (IPlist.size() != 4)
le->setText("0.0.0.0");
qDebug() << le->text();
QString ip;
ip = "";
for (int i = 0; i < IPlist.size(); i++) {
bool issave = false;
for (int j = 0; j < IPlist[i].length(); j++) {
if (IPlist[i][j] == "0" && !issave)
continue;
else {
issave = true;
ip += IPlist[i][j];
}
}
if(i<3)
ip += ".";
else if(i==3 && ip == "...")
ip = "0.0.0.0";
}
le->setText(ip);
}
//QWIntSpinDelegate***********************************************************************************************************
QWidget* QWIntSpinDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QSpinBox* editor = new QSpinBox(parent);
editor->setFrame(false);
editor->setMinimum(0);
editor->setMaximum(10000);
return editor;
}
void QWIntSpinDelegate::setEditorData(QWidget* editor, const QModelIndex& index)const
{
//从数据模型中获取数据,显示到代理组件中
int value = index.model()->data(index, Qt::EditRole).toInt();
QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
spinBox->setValue(value);
}
void QWIntSpinDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index)const
{
//将代理组件的数据保存到数据模型中
QSpinBox* spinBox = static_cast<QSpinBox*>(editor);
spinBox->interpretText();
int value = spinBox->value();
model->setData(index, value, Qt::EditRole);
}
void QWIntSpinDelegate::updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
//设置组件大小
editor->setGeometry(option.rect);
}
void QWIntSpinDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index)const
{
QStyleOptionViewItem newoption(option);
newoption.displayAlignment = Qt::AlignCenter;
QStyledItemDelegate::paint(painter, newoption, index);
}
//IP重写**************************************************************************************************************************
QWidget* QWLineEditDelegate_IP::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
QLineEdit* editor = new QLineEdit(parent);
editor->setValidator(new QRegExpValidator(QRegExp("^(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.?(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.?(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])\.?(1?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])|^\s*$"), parent));
//editor->setInputMask("000.000.000.000");//;0表示删除时,默认填充0;并且使正则有效
editor->setFrame(false);
editor->setPlaceholderText("0.0.0.0");
qDebug() << editor->text();
return editor;
}