ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

QTableView表格控件代理详解

2021-09-18 14:32:50  阅读:366  来源: 互联网

标签:控件 const VariableItem 代理 QTableView 详解 QWidget variable


这里写目录标题

简单代理控件

新创建的表格是可以直接进行编辑,默认效果类似于QLineEdit,但是如果想要在表格上嵌入一些复杂的控件默认的效果就不行了,例如下面的例子:

简单代理设置
其中在双击表格控件后会出现一个下拉框,这种效果就需要使用代理来实现,代码如下所示:

class VariableDelegate
	: public QStyledItemDelegate
{
	Q_OBJECT
public:
	explicit VariableDelegate(QObject* _parent = nullptr);
	~VariableDelegate();

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

};

QWidget* VariableDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	QComboBox* delegate_item = new QComboBox(parent);
	delegate_item->addItems(QStringList() << "c_1" << "c_2");
	return delegate_item;
}
// tableview给第二列设置代理控件
setItemDelegateForColumn(1, new VariableDelegate(this));
// tableview给全部单元格设置代理控件
setItemDelegate(new VariableDelegate(this));
// tableview给第二行设置代理控件
setItemDelegateForRow(1, new VariableDelegate(this));

重写关键函数

要开发代理控件首先要实现QStyledItemDelegate中的createEditor()函数,将要放置的控件在该函数中创建并返回控件,在创建表格后将代理设置给QTableView,就能实现代理效果。

在实现createEditor()函数时必须将第一个参数(parent)作为父类设置给创建后需要返回的控件,否则控件不会出现在指定位置上。

最简单的代理控件的实现方式就是实现createEditor()函数即可,但是一般在开发代理控件时肯定有比较复杂的情况,因此面对复杂的情况代理的开发一般至少实现三个函数,具体如下表所示:

函数名称描述
createEditor()返回一个控件对象
setEditorData()将界面上显示的值设置到具体控件上
setModelData()返回给模型用户修改过的数据

创建一个复杂一点控件来分别解释一下这三个关键函数的作用,例如,可以将一个组合的自定义控件嵌入到表格中,组合自定义控件如下:

#include <QtWidgets>

class VariableItem
        : public QWidget
{
public:
    explicit VariableItem(QWidget* _parent = nullptr);
    ~VariableItem() override;

	void SetText(const QString & _text);

	QString GetText();

private:
    void InitializeUI();

private:
    QLineEdit*							variable_show_;
    QPushButton*						variable_select_;
};
#include "variable_item.h"
VariableItem::VariableItem(QWidget *_parent)
        : QWidget(_parent)
        , variable_show_(nullptr)
        , variable_select_(nullptr) {
    InitializeUI();
}

VariableItem::~VariableItem() = default

void VariableItem::SetText(const QString & _text) {
	variable_show_->setText(_text);
}

QString VariableItem::GetText() {
	return variable_show_->text();
}

void VariableItem::InitializeUI() {
    QHBoxLayout* variable_main_layout = new QHBoxLayout();
    variable_main_layout->setMargin(0);
    variable_show_ = new QLineEdit(this);
    variable_main_layout->addWidget(variable_show_, 1);
    QPushButton* variable_btn = new QPushButton("Select", this);
    variable_main_layout->addWidget(variable_btn);
    setLayout(variable_main_layout);
    setContentsMargins(0, 0, 0, 0);
}

这段代码在普通的情况下直接可以独立显示出来,其中在窗体的水平方向上放置了一个QLineEditQPushButton,具体如下所示:

复杂控件内容

这种复杂的自定义控件同样可以放到createEditor()函数中,作为一个代理控件返回,具体代码如下:

QWidget* VariableDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const
{
	VariableItem* item = new VariableItem(parent);
	return item;
}

双击表格控件时就可以在单元格内看到该复杂控件,效果如下:
复杂控件代理演示
可以,这个控件是可以修改数据,但是当修改数据并离开单元格后,单元格没有显示当前输入的数据,这是就用到了setModelData()函数,该函数可以将控件的数据设置给单元格去显示。

void VariableDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const
{
	VariableItem* item = qobject_cast<VariableItem*>(editor);
	if (item != nullptr) {
		model->setData(index, item->GetText(), Qt::EditRole);
	}
}

注意设置Data的标识字段时要设置Qt::EditRole,该标志就是QTableView从Model取值显示时的标志,显示效果如下:

修改复杂控件_1
修改复杂控件_2
现在当离开单元格的编辑状态后已经可以在单元格中显示刚刚输入的内容了,可以配合按钮实现例如选择文件夹、文件或者日期等操作。

当再次双击单元格时,将显示的内容写入到复杂控件中可以重写setEditorData()函数,该函数就可以从当前选中的单元格中返回内容,然后使用Qt::EditRole标识值将数据取出设置即可。

void VariableDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const
{
	QString value = index.model()->data(index, Qt::EditRole).toString();
	VariableItem* item = qobject_cast<VariableItem*>(editor);
	if (item != nullptr) {
		item->SetText(value);
	}
}

至此基本表格代理控件就开发完成了。

代理控件析构

createEditor()函数中会大量创建QWidget对象,这些对象会在setModelData()结束后自动被析构因此不需要自己取手动进行管理。演示如下:

// 给代理控件添加析构函数,并打印数据
VariableItem::~VariableItem() {
    qInfo() << "delete VariableItem";
}

// 添加数据打印
void VariableDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const {
    qInfo() << "setModelData";
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HqkXiFeY-1631945877670)(image/代理自动析构.gif)]

标签:控件,const,VariableItem,代理,QTableView,详解,QWidget,variable
来源: https://blog.csdn.net/u010031316/article/details/120366295

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有