需求:在QTableWidget界面中,需要对不同的Item设置不同的输入限制
解决方案1:
通过setCellWidget函数在表格Item上设置界面组件,但此方法需要管理创建的界面组件,若表格显示的内容较多时,管理的组件也越多,且设置QSS样式后,表格与界面组件样式不统一影响美观。
解决方案2:
通过setItemDelegate函数设置表格代理,受到QtTreePropertyBrowser原理启发,在createEditor中根据不同的类型创建不同的组件。
效果展示:
代码:
#ifndef ITEMDELEGATE_H
#define ITEMDELEGATE_H
#include <QStyledItemDelegate>
#define EditorType "editorType"
#define ToolTip "tooltip"
//QLineEdit String
#define InputMask "inputMask"
#define MaxLength "maxLength"
#define RegExp "regExp"
//QSpinBox Int
#define Minimum "minimum"
#define Maximum "maximum"
#define SingleStep "step"
#define Prefix "prefix"
#define Suffix "suffix"
//QDoubleSpinBox Double
#define Decimals "decimals"
//QCheckBox Bool
//QDate
#define DisplayFormat "displayFormat"
#define MaximumDateTime "MaximumDateTime"
#define MinimumDateTime "MinimumDateTime"
//QComboBox List
#define ComboBoxValue "comboBoxValue"
#define ItemDelegateRole (Qt::UserRole)
class QLineEdit;
class QSpinBox;
class QDoubleSpinBox;
class QCheckBox;
class QDateEdit;
class QTimeEdit;
class QDateTimeEdit;
class QComboBox;
/*!
* \brief The ItemDelegate class 自定义代理
* 通过获取index.data(Qt::UserRole).toHash()中的键值
* 创建对应的代理编辑器
*/
class ItemDelegate : public QStyledItemDelegate
{
public:
ItemDelegate(QObject* pParent = Q_NULLPTR);
virtual ~ItemDelegate();
/*!
* \brief createEditor 创建编辑器
* \param pParent 父对象
* \param option 设置
* \param index 索引
* \return
*/
QWidget *createEditor(QWidget *pParent, const QStyleOptionViewItem &option, const QModelIndex &index) const;
/*!
* \brief setEditorData 设置编辑器数据
* \param pEditor 编辑器
* \param index 索引
*/
void setEditorData(QWidget *pEditor, const QModelIndex &index) const;
/*!
* \brief setModelData 设置模型数据
* \param pEditor 编辑器
* \param model 模型
* \param index 索引
*/
void setModelData(QWidget *pEditor, QAbstractItemModel *model, const QModelIndex &index) const;
/*!
* \brief updateEditorGeometry 更新编辑器样式
* \param pEditor 编辑器
* \param option 设置
* \param index 索引
*/
void updateEditorGeometry(QWidget *pEditor, const QStyleOptionViewItem &option, const QModelIndex &index) const;
private:
/*!
* \brief createLineEdit 创建QLineEdit
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QLineEdit *createLineEdit(const QVariantHash& hash, QWidget *pParent) const;
/*!
* \brief createSpinBox 创建QSpinBox
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QSpinBox *createSpinBox(const QVariantHash& hash, QWidget *pParent) const;
/*!
* \brief createDoubleSpinBox 创建QDoubleSpinBox
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QDoubleSpinBox* createDoubleSpinBox(const QVariantHash& hash, QWidget *pParent) const;
/*!
* \brief createCheckBox 创建QCheckBox
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QCheckBox *createCheckBox(const QVariantHash& hash, QWidget *pParent) const;
/*!
* \brief createDateEdit 创建QDateEdit
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QDateEdit *createDateEdit(const QVariantHash& hash, QWidget *pParent) const;
/*!
* \brief createTimeEdit 创建QTimeEdit
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QTimeEdit *createTimeEdit(const QVariantHash& hash, QWidget *pParent) const;
/*!
* \brief createDateTimeEdit 创建QDateTimeEdit
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QDateTimeEdit *createDateTimeEdit(const QVariantHash& hash, QWidget *pParent) const;
/*!
* \brief createDateTimeEdit 创建QComboBox
* \param hash 属性容器
* \param pParent 父对象
* \return 指针
*/
QComboBox *createComboBox(const QVariantHash& hash, QWidget *pParent)const;
};
#endif // ITEMDELEGATE_H
#include "ItemDelegate.h"
#include <QLineEdit>
#include <QSpinBox>
#include <QDoubleSpinBox>
#include <QCheckBox>
#include <QDateEdit>
#include <QTimeEdit>
#include <QDateTimeEdit>
#include <QComboBox>
ItemDelegate::ItemDelegate(QObject *pParent) :
QStyledItemDelegate(pParent)
{
}
ItemDelegate::~ItemDelegate()
{
}
QWidget *ItemDelegate::createEditor(QWidget *pParent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(option)
QVariant value = index.data(Qt::UserRole);
if(QVariant::Hash == value.type())
{
const QVariantHash hash = index.data(Qt::UserRole).toHash();
if(hash.contains(EditorType))
{
switch (hash[EditorType].type())
{
case QVariant::String:
return createLineEdit(hash, pParent);
case QVariant::Int:
return createSpinBox(hash, pParent);
case QVariant::Double:
return createDoubleSpinBox(hash, pParent);
case QVariant::Bool:
return createCheckBox(hash, pParent);
case QVariant::Date:
return createDateEdit(hash, pParent);
case QVariant::Time:
return createTimeEdit(hash, pParent);
case QVariant::DateTime:
return createDateTimeEdit(hash, pParent);
case QVariant::List:
return createComboBox(hash, pParent);
default:
break;
}
}
}
return new QLineEdit(pParent);
}
void ItemDelegate::setEditorData(QWidget *pEditor, const QModelIndex &index) const
{
QVariant value = index.data(Qt::UserRole);
if(QVariant::Hash == value.type())
{
const QVariantHash hash = index.data(Qt::UserRole).toHash();
if(hash.contains(EditorType))
{
switch (hash[EditorType].type())
{
case QVariant::String:
{
QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(pEditor);
if(pLineEdit)
{
pLineEdit->setText(index.data().toString());
}
return;
}
case QVariant::Int:
{
QSpinBox* pSpinBox = qobject_cast<QSpinBox*>(pEditor);
if(pSpinBox)
{
pSpinBox->setValue(index.data().toString().toInt());
}
return;
}
case QVariant::Double:
{
QDoubleSpinBox* pDSpinBox = qobject_cast<QDoubleSpinBox*>(pEditor);
if(pDSpinBox)
{
pDSpinBox->setValue(index.data().toString().toInt());
}
return;
}
case QVariant::Bool:
{
QCheckBox* pCheckBox = qobject_cast<QCheckBox*>(pEditor);
if(pCheckBox)
{
bool bChecked = index.data().toString() == "True" ? true : false;
pCheckBox->setChecked(bChecked);
pCheckBox->setText(bChecked ? "True" : "False");
}
return;
}
case QVariant::Date:
{
QDateEdit* pDateEdit = qobject_cast<QDateEdit*>(pEditor);
if(pDateEdit)
{
QDate date;
if(hash.contains(DisplayFormat))
{
date = QDate::fromString(index.data().toString(), hash[DisplayFormat].toString());
}
else
{
date = QDate::fromString(index.data().toString());
}
pDateEdit->setDate(date);
}
return;
}
case QVariant::Time:
{
QTimeEdit* pTimeEdit = qobject_cast<QTimeEdit*>(pEditor);
if(pTimeEdit)
{
QTime time;
if(hash.contains(DisplayFormat))
{
time = QTime::fromString(index.data().toString(), hash[DisplayFormat].toString());
}
else
{
time = QTime::fromString(index.data().toString());
}
pTimeEdit->setTime(time);
}
return;
}
case QVariant::DateTime:
{
QDateTimeEdit* pDateTimeEdit = qobject_cast<QDateTimeEdit*>(pEditor);
if(pDateTimeEdit)
{
QDateTime dateTime;
if(hash.contains(DisplayFormat))
{
dateTime = QDateTime::fromString(index.data().toString(), hash[DisplayFormat].toString());
}
else
{
dateTime = QDateTime::fromString(index.data().toString());
}
pDateTimeEdit->setDateTime(dateTime);
}
return;
}
case QVariant::List:
{
QComboBox* pComboBox = qobject_cast<QComboBox*>(pEditor);
if(pComboBox)
{
pComboBox->setCurrentText(index.data().toString());
}
return;
}
default:
break;
}
}
}
QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(pEditor);
if(pLineEdit)
{
pLineEdit->setText(index.data().toString());
}
}
void ItemDelegate::setModelData(QWidget *pEditor, QAbstractItemModel *model, const QModelIndex &index) const
{
QVariant value = index.data(Qt::UserRole);
if(QVariant::Hash == value.type())
{
const QVariantHash hash = index.data(Qt::UserRole).toHash();
if(hash.contains(EditorType))
{
switch (hash[EditorType].type())
{
case QVariant::String:
{
QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(pEditor);
if(pLineEdit)
{
model->setData(index, pLineEdit->text());
}
return;
}
case QVariant::Int:
{
QSpinBox* pSpinBox = qobject_cast<QSpinBox*>(pEditor);
if(pSpinBox)
{
model->setData(index, QString::number(pSpinBox->value()));
}
return;
}
case QVariant::Double:
{
QDoubleSpinBox* pDSpinBox = qobject_cast<QDoubleSpinBox*>(pEditor);
if(pDSpinBox)
{
model->setData(index, QString::number(pDSpinBox->value()));
}
return;
}
case QVariant::Bool:
{
QCheckBox* pCheckBox = qobject_cast<QCheckBox*>(pEditor);
if(pCheckBox)
{
model->setData(index, pCheckBox->checkState() == Qt::Checked ? "True" : "False");
}
return;
}
case QVariant::Date:
{
QDateEdit* pDateEdit = qobject_cast<QDateEdit*>(pEditor);
if(pDateEdit)
{
QString str;
if(hash.contains(DisplayFormat))
{
str = pDateEdit->date().toString(hash[DisplayFormat].toString());
}
else
{
str = pDateEdit->date().toString();
}
model->setData(index, str);
}
return;
}
case QVariant::Time:
{
QTimeEdit* pTimeEdit = qobject_cast<QTimeEdit*>(pEditor);
if(pTimeEdit)
{
QString str;
if(hash.contains(DisplayFormat))
{
str = pTimeEdit->time().toString(hash[DisplayFormat].toString());
}
else
{
str = pTimeEdit->time().toString();
}
model->setData(index, str);
}
return;
}
case QVariant::DateTime:
{
QDateTimeEdit* pDateTimeEdit = qobject_cast<QDateTimeEdit*>(pEditor);
if(pDateTimeEdit)
{
QString str;
if(hash.contains(DisplayFormat))
{
str = pDateTimeEdit->dateTime().toString(hash[DisplayFormat].toString());
}
else
{
str = pDateTimeEdit->dateTime().toString();
}
model->setData(index, str);
}
return;
}
case QVariant::List:
{
QComboBox* pComboBox = qobject_cast<QComboBox*>(pEditor);
if(pComboBox)
{
model->setData(index, pComboBox->currentText());
}
return;
}
default:
break;
}
}
}
QLineEdit* pLineEdit = qobject_cast<QLineEdit*>(pEditor);
if(pLineEdit)
{
model->setData(index, pLineEdit->text());
}
}
void ItemDelegate::updateEditorGeometry(QWidget *pEditor, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
Q_UNUSED(index)
pEditor->setGeometry(option.rect);
}
QLineEdit *ItemDelegate::createLineEdit(const QVariantHash &hash, QWidget *pParent) const
{
QLineEdit* pLineEdit = new QLineEdit(pParent);
//设置提示文本
if(hash.contains(ToolTip))
{
pLineEdit->setToolTip(hash[ToolTip].toString());
}
//设置输入格式
if(hash.contains(InputMask))
{
pLineEdit->setInputMask(hash[InputMask].toString());
}
//设置最大输入字符个数
if(hash.contains(MaxLength))
{
pLineEdit->setMaxLength(hash[MaxLength].toInt());
}
//设置输入限制
if(hash.contains(RegExp))
{
pLineEdit->setValidator(new QRegExpValidator(QRegExp(hash[RegExp].toString()), pLineEdit));
}
return pLineEdit;
}
QSpinBox *ItemDelegate::createSpinBox(const QVariantHash &hash, QWidget *pParent) const
{
QSpinBox* pSpinBox = new QSpinBox(pParent);
//设置提示文本
if(hash.contains(ToolTip))
{
pSpinBox->setToolTip(hash[ToolTip].toString());
}
//设置最小值
if(hash.contains(Minimum))
{
pSpinBox->setMinimum(hash[Minimum].toInt());
}
//设置最大值
if(hash.contains(Maximum))
{
pSpinBox->setMaximum(hash[Maximum].toInt());
}
//设置步长
if(hash.contains(SingleStep))
{
pSpinBox->setSingleStep(hash[SingleStep].toInt());
}
//设置前缀文本
if(hash.contains(Prefix))
{
pSpinBox->setPrefix(hash[Prefix].toString());
}
//设置后缀文本
if(hash.contains(Suffix))
{
pSpinBox->setSuffix(hash[Suffix].toString());
}
return pSpinBox;
}
QDoubleSpinBox *ItemDelegate::createDoubleSpinBox(const QVariantHash &hash, QWidget *pParent) const
{
QDoubleSpinBox* pDSpinBox = new QDoubleSpinBox(pParent);
//设置提示文本
if(hash.contains(ToolTip))
{
pDSpinBox->setToolTip(hash[ToolTip].toString());
}
//设置最小值
if(hash.contains(Minimum))
{
pDSpinBox->setMinimum(hash[Minimum].toDouble());
}
//设置最大值
if(hash.contains(Maximum))
{
pDSpinBox->setMaximum(hash[Maximum].toDouble());
}
//设置步长
if(hash.contains(SingleStep))
{
pDSpinBox->setSingleStep(hash[SingleStep].toDouble());
}
//设置前缀文本
if(hash.contains(Prefix))
{
pDSpinBox->setPrefix(hash[Prefix].toString());
}
//设置后缀文本
if(hash.contains(Suffix))
{
pDSpinBox->setSuffix(hash[Suffix].toString());
}
return pDSpinBox;
}
QCheckBox *ItemDelegate::createCheckBox(const QVariantHash &hash, QWidget *pParent) const
{
Q_UNUSED(hash)
QCheckBox* pCheckBox = new QCheckBox(pParent);
pCheckBox->setChecked(false);
pCheckBox->setText("False");
pCheckBox->setStyleSheet(QString("QCheckBox{background-color: white;}"));
connect(pCheckBox, &QCheckBox::clicked, this, [=](bool bChecked){
pCheckBox->setText(bChecked ? "True" : "False");
});
//设置提示文本
if(hash.contains(ToolTip))
{
pCheckBox->setToolTip(hash[ToolTip].toString());
}
return pCheckBox;
}
QDateEdit *ItemDelegate::createDateEdit(const QVariantHash &hash, QWidget *pParent) const
{
QDateEdit* pDateEdit = new QDateEdit(pParent);
//设置提示文本
if(hash.contains(ToolTip))
{
pDateEdit->setToolTip(hash[ToolTip].toString());
}
//设置显示样式
if(hash.contains(DisplayFormat))
{
pDateEdit->setDisplayFormat(hash[DisplayFormat].toString());
}
//设置最大日期时间
if(hash.contains(MaximumDateTime))
{
pDateEdit->setMaximumDateTime(hash[MaximumDateTime].toDateTime());
}
//设置最小日期时间
if(hash.contains(MinimumDateTime))
{
pDateEdit->setMinimumDateTime(hash[MinimumDateTime].toDateTime());
}
return pDateEdit;
}
QTimeEdit *ItemDelegate::createTimeEdit(const QVariantHash &hash, QWidget *pParent) const
{
QTimeEdit* pTimeEdit = new QTimeEdit(pParent);
//设置提示文本
if(hash.contains(ToolTip))
{
pTimeEdit->setToolTip(hash[ToolTip].toString());
}
//设置显示样式
if(hash.contains(DisplayFormat))
{
pTimeEdit->setDisplayFormat(hash[DisplayFormat].toString());
}
//设置最大日期时间
if(hash.contains(MaximumDateTime))
{
pTimeEdit->setMaximumDateTime(hash[MaximumDateTime].toDateTime());
}
//设置最小日期时间
if(hash.contains(MinimumDateTime))
{
pTimeEdit->setMinimumDateTime(hash[MinimumDateTime].toDateTime());
}
return pTimeEdit;
}
QDateTimeEdit *ItemDelegate::createDateTimeEdit(const QVariantHash &hash, QWidget *pParent) const
{
QDateTimeEdit* pDateTimeEdit = new QDateTimeEdit(pParent);
//设置提示文本
if(hash.contains(ToolTip))
{
pDateTimeEdit->setToolTip(hash[ToolTip].toString());
}
//设置显示样式
if(hash.contains(DisplayFormat))
{
pDateTimeEdit->setDisplayFormat(hash[DisplayFormat].toString());
}
//设置最大日期时间
if(hash.contains(MaximumDateTime))
{
pDateTimeEdit->setMaximumDateTime(hash[MaximumDateTime].toDateTime());
}
//设置最小日期时间
if(hash.contains(MinimumDateTime))
{
pDateTimeEdit->setMinimumDateTime(hash[MinimumDateTime].toDateTime());
}
return pDateTimeEdit;
}
QComboBox *ItemDelegate::createComboBox(const QVariantHash &hash, QWidget *pParent) const
{
QComboBox* pComboBox = new QComboBox(pParent);
//设置提示文本
if(hash.contains(ToolTip))
{
pComboBox->setToolTip(hash[ToolTip].toString());
}
//设置List
if(hash.contains(ComboBoxValue))
{
pComboBox->addItems(hash[ComboBoxValue].toStringList());
}
return pComboBox;
}
ui->tableWidget->setItemDelegate(new ItemDelegate);
QTableWidgetItem* pItem = new QTableWidgetItem;
pItem->setText("123");
ui->tableWidget->setItem(0, 0, pItem);
QVariantHash hash;
hash.insert(EditorType, QVariant::String);
hash.insert(MaxLength, 10);
pItem->setData(ItemDelegateRole, hash);
pItem = new QTableWidgetItem;
pItem->setText("234");
ui->tableWidget->setItem(0, 1, pItem);
hash.clear();
hash.insert(EditorType, QVariant::Int);
hash.insert(Minimum, 0);
hash.insert(Maximum, 1000);
pItem->setData(ItemDelegateRole, hash);
pItem = new QTableWidgetItem;
pItem->setText("True");
ui->tableWidget->setItem(0, 2, pItem);
hash.clear();
hash.insert(EditorType, QVariant::Bool);
pItem->setData(ItemDelegateRole, hash);
pItem = new QTableWidgetItem;
pItem->setText("Test1");
ui->tableWidget->setItem(1, 0, pItem);
hash.clear();
hash.insert(EditorType, QVariant::List);
hash.insert(ComboBoxValue, QStringList() << "Test1" << "Test2" << "Test3");
pItem->setData(ItemDelegateRole, hash);
pItem = new QTableWidgetItem;
QString strFormat = QString("yyyy/MM/dd hh:mm:ss");
pItem->setText(QDateTime::currentDateTime().toString(strFormat));
ui->tableWidget->setItem(1, 1, pItem);
hash.clear();
hash.insert(EditorType, QVariant::DateTime);
hash.insert(DisplayFormat, strFormat);
pItem->setData(ItemDelegateRole, hash);