Qt的委托代理机制

  • 委托是Qt中的一种机制,用于在Qt模型/视图架构中处理特定类型的数据。委托提供了一种方便的方法来定制特定类型的数据的显示和编辑。
  • 委托可以做以下事情:

编辑特定类型的数据: 通过创建编辑器来编辑特定类型的数据,例如日期,数值等。

渲染特定类型的数据: 通过定制单元格的外观来渲染特定类型的数据,例如颜色,字体等;

支持不同类型的编辑器: 支持不同类型的编辑器,例如文本编辑器,下拉列表编辑器等;

处理编辑器的事件: 通过实现eventFilter()方法来处理编辑器的事件,如键盘事件;

更新编辑器的尺寸: 通过实现sizeHint()方法来更新编辑器的尺寸;

数据验证: 通过实现editorEvent()来验证编辑器中的数据是否合法。

  • 委托的常见应用场景包括:

表格和列表视图: 在表格和列表视图中使用委托可以方便地编辑单元格中的数据,并定制单元格的外观

属性编辑器: 使用委托可以创建自定义属性编辑器来编辑特定类型的属性

文件对话框: 使用委托可以定制文件对话框中的文件列表的外观

以QTableView为例子:

  1. 需要为QTableView设置一个model
  • 也可以自定义model,继承QStandardItemModel;
  1. 为QTableView设置Delegate
  • 继承QStandardItemModel、QItemDelegate或者QStyledItemDelegate;
  • QItemDelegate是QAbstractItemDelegate的子类,它提供了一种通用的委托类;
  • QStyledItemDelegate是QItemDelegate的子类,它使用Qt Style Sheets来渲染单元格中的数据,这样可以更好地与应用程序的外观保持一致。它还提供了一些额外的功能,如支持自定义编辑器和支持编辑器工厂,这样可以更好地管理编辑器;
  1. 委托类需要重写对应的函数,比如:
  1. QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option,const QModelIndex &index) const;
  2. void setEditorData(QWidget *editor, const QModelIndex &index) const;
  3. void setModelData(QWidget *editor, QAbstractItemModel *model,const QModelIndex &index) const;
  4. void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option, const QModelIndex &index) const;
  5. void paint(QPainter *painter, const QStyleOptionViewItem &option,const QModelIndex & index) const;
  6. QSize sizeHint(const QStyleOptionViewItem &option,const QModelIndex &index) const;
  7. bool eventFilter(QObject *object, QEvent *event) ;
  8. bool editorEvent(QEvent *event, QAbstractItemModel *model,
    const QStyleOptionViewItem &option, const QModelIndex &index) override;

创建编辑器

cpp 复制代码
QWidget* TableViewDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	QSpinBox *sbox = new QSpinBox(parent);
	sbox->setRange(sboxMinValue, sboxMaxValue);
	sbox->setSuffix(sboxSuffixStr);
	sbox->setPrefix(sboxPrefixStr);
	sbox->setSingleStep(sboxSingleStep);
	sbox->setStepType(sboxStepType);
	sbox->setValue(sboxInitValue);
	return  sbox;
}

设置编辑器数据 setEditorData

cpp 复制代码
void TableViewDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
	auto value = index.model()->data(index, Qt::EditRole);
	QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
	spinBox->setValue(value.toInt());
}

设置模型数据 setModelData

cpp 复制代码
void TableViewDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index)const
{
	QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
	QVariant value = spinBox->value();
	model->setData(index, value, Qt::EditRole);

}

更新编辑器集合属性 updateEditorGeometry

cpp 复制代码
void TableViewDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index)const
{
	editor->setGeometry(option.rect);
}

部分代码如下:

cpp 复制代码
#include <QStyledItemDelegate>
#include <QItemDelegate>
#include <QStandardItemModel>
/*
*
*
*	创建一个QSpinBox设置相关参数函数
*
*
*/
class TableViewDelegate  : public QStyledItemDelegate
{
	Q_OBJECT

public:
	TableViewDelegate(QObject *parent = nullptr);
	~TableViewDelegate();

	// editing
	QWidget *createEditor(QWidget *parent,const QStyleOptionViewItem &option,const QModelIndex &index)const;
	void setEditorData(QWidget *editor, const QModelIndex &index) const ;
	void setModelData(QWidget *editor,QAbstractItemModel *model,const QModelIndex &index)const;
	void updateEditorGeometry(QWidget *editor,const QStyleOptionViewItem &option,const QModelIndex &index)const;
private:
	void init();
public:
	/*QSpinBox设置相关参数函数*/
	void setSboxMaxValue(const int max);
	void setSboxMinValue(const int min);
	void setSboxPrefixStr(const QString &prefix);
	void setSboxSuffixStr(const QString &suffix);
	void setSboxSingleStep(const int SingleStep);
	void setSboxInitValue(const int initValue);
	void setSboxStepType(QAbstractSpinBox::StepType st);
private:
	/*QSpinBox相关参数*/
	int sboxMaxValue;/*微调框的最大值*/
	int sboxMinValue;/*微调框的最小值*/

	QString sboxPrefixStr;/*微调框前缀*/
	QString sboxSuffixStr;/*微调框后缀*/

	int sboxSingleStep;/*微调框步长*/
	int sboxInitValue;/*微调框初始值*/

	QAbstractSpinBox::StepType sboxStepType;/*微调框步长类型*/
};

Delegate.cpp
TableViewDelegate::TableViewDelegate(QObject *parent): QStyledItemDelegate(parent)
{
}
TableViewDelegate::~TableViewDelegate()
{
}
QWidget* TableViewDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
	QSpinBox *sbox = new QSpinBox(parent);
	sbox->setRange(sboxMinValue, sboxMaxValue);
	sbox->setSuffix(sboxSuffixStr);
	sbox->setPrefix(sboxPrefixStr);
	sbox->setSingleStep(sboxSingleStep);
	sbox->setStepType(sboxStepType);
	sbox->setValue(sboxInitValue);
	return  sbox;
}

//将模型中的数据赋值给编辑器
void TableViewDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
{
	auto value = index.model()->data(index, Qt::EditRole);
	QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
	spinBox->setValue(value.toInt());
}
void TableViewDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index)const
{
	QSpinBox *spinBox = static_cast<QSpinBox*>(editor);
	QVariant value = spinBox->value();
	model->setData(index, value, Qt::EditRole);
}
void TableViewDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index)const
{
	editor->setGeometry(option.rect);
}
/*QSpinBox设置相关参数函数*/
void TableViewDelegate::setSboxMaxValue(const int max)
{
	sboxMaxValue = max;
}
void TableViewDelegate::setSboxMinValue(const int min)
{
	sboxMinValue = min;
}
void TableViewDelegate::setSboxPrefixStr(const QString &prefix) 
{
	sboxPrefixStr = prefix;
}
void TableViewDelegate::setSboxSuffixStr(const QString &suffix)
{
	sboxSuffixStr = suffix;
}
void TableViewDelegate::setSboxSingleStep(const int SingleStep)
{
	sboxSingleStep = SingleStep;
}
void TableViewDelegate::setSboxInitValue(const int initValue)
{
	sboxInitValue = initValue;
}
void TableViewDelegate::setSboxStepType(QAbstractSpinBox::StepType st)
{
	sboxStepType = st;
}
void TableViewDelegate::init()
{
}
//在QTableView中使用
void init() 
{
	QStringList columnNames;
	columnNames << "QSpinBox" << "QComboBox" << "QCheckBox" << ".....";
	model = new QStandardItemModel;
	model->setRowCount(10);
	model->setHorizontalHeaderLabels(columnNames);
	ui->tableView->setModel(model);
	TableViewDelegate * tabDelegate = new TableViewDelegate;
	tabDelegate->setSboxMinValue(0);
	tabDelegate->setSboxMaxValue(100);
	tabDelegate->setSboxSingleStep(2);
	tabDelegate->setSboxInitValue(10);
	//设置第一列为TableViewDelegate 样式
	ui->tableView->setItemDelegateForColumn(0, tabDelegate);
}
相关推荐
一颗花生米。14 分钟前
深入理解JavaScript 的原型继承
java·开发语言·javascript·原型模式
问道飞鱼15 分钟前
Java基础-单例模式的实现
java·开发语言·单例模式
学习使我快乐0118 分钟前
JS进阶 3——深入面向对象、原型
开发语言·前端·javascript
通信仿真实验室1 小时前
(10)MATLAB莱斯(Rician)衰落信道仿真1
开发语言·matlab
勿语&1 小时前
Element-UI Plus 暗黑主题切换及自定义主题色
开发语言·javascript·ui
吾爱星辰5 小时前
Kotlin 处理字符串和正则表达式(二十一)
java·开发语言·jvm·正则表达式·kotlin
ChinaDragonDreamer5 小时前
Kotlin:2.0.20 的新特性
android·开发语言·kotlin
IT良5 小时前
c#增删改查 (数据操作的基础)
开发语言·c#
Kalika0-06 小时前
猴子吃桃-C语言
c语言·开发语言·数据结构·算法
_.Switch6 小时前
Python Web 应用中的 API 网关集成与优化
开发语言·前端·后端·python·架构·log4j