QStyledItemDelegate的使用方法

QStyledItemDelegate 是 Qt 框架中用于为模型/视图框架提供数据项显示和编辑的一个类。

1. 创建 QStyledItemDelegate 实例

通常,你不需要直接实例化 QStyledItemDelegate,因为它是默认的委托。但如果你需要自定义显示和编辑行为,你可以继承 QStyledItemDelegate 并创建自己的委托类。

2. 继承 QStyledItemDelegate 并重写必要的方法

createEditor:返回用于编辑由索引指定的项的小部件。你需要根据数据类型创建适当的编辑器(如 QLineEdit、QSpinBox 等)。
setEditorData:从模型索引指定的数据模型项设置要由编辑器显示和编辑的数据。
setModelData:从编辑器小部件获取数据,并将其存储在项目索引处的指定模型中。
updateEditorGeometry:更新由索引指定的项的编辑器几何形状。

3. 设置委托属性(可选)

如果你自定义了 QStyledItemDelegate 的子类,并希望设置一些额外的属性(如字体、颜色等),你可以在子类中提供相应的设置方法。

4. 应用委托到视图

使用视图(如 QTableView、QListView)的 setItemDelegate 方法来应用你的委托。例如:

MyStyledItemDelegate *delegate = new MyStyledItemDelegate(this);

ui->tableView->setItemDelegate(delegate);

5. 自定义绘制和数据处理(可选)

如果你需要更精细地控制项的绘制或数据处理,你可以重写 paint、sizeHint 等方法。
你也可以使用 setItemEditorFactory 来设置自定义的编辑器工厂,以创建特定的编辑器小部件。

6. 注意事项

确保你的模型和视图已经正确设置,并且数据模型中的数据可以被委托正确地读取和写入。
如果你的委托需要处理复杂的数据类型或交互,确保你的实现是健壮的,并处理所有可能的边缘情况。
通过遵循上述步骤,你可以使用 QStyledItemDelegate(或其子类)来定制 Qt 模型/视图框架中的数据项显示和编辑行为。

7、demo示例

在QtreeWidget中通过委托绘制一个组合控件(智能补全编辑框+按钮),先看效果:

#pragma once

#include <QStyledItemDelegate>
#include <QPainter>
#include <QApplication>

class MyStyledDelegate  : public QStyledItemDelegate
{
	Q_OBJECT

public:
	MyStyledDelegate(QObject *parent);
	~MyStyledDelegate();

	void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
	QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override;  
	void setEditorData(QWidget *editor, const QModelIndex &index) const override;  
	void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override;  
	void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const override;
private slots:
	void onEditFinished();
};
#include "MyStyledDelegate.h"
#include "MyEditor.h"

MyStyledDelegate::MyStyledDelegate(QObject *parent)
	: QStyledItemDelegate(parent)
{}

MyStyledDelegate::~MyStyledDelegate()
{}

void MyStyledDelegate::paint(QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
	//此处可以自定义绘制...
	return QStyledItemDelegate::paint(painter, option, index);
}

QWidget * MyStyledDelegate::createEditor(QWidget * parent, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
	auto editor = new MyEditor(parent);
	connect(editor, &MyEditor::editFinished, this, &MyStyledDelegate::onEditFinished);
	return editor;
}

void MyStyledDelegate::setEditorData(QWidget * editor, const QModelIndex & index) const
{
	QString value = index.model()->data(index, Qt::EditRole).toString();
	auto myEditor = qobject_cast<MyEditor*>(editor);
	myEditor->setText(value);
}

void MyStyledDelegate::setModelData(QWidget * editor, QAbstractItemModel * model, const QModelIndex & index) const
{
	auto myEditor = qobject_cast<MyEditor*>(editor);
	auto value = myEditor->text();
	model->setData(index, value, Qt::EditRole);
}

void MyStyledDelegate::updateEditorGeometry(QWidget * editor, const QStyleOptionViewItem & option, const QModelIndex & index) const
{
	editor->setGeometry(option.rect);
}

void MyStyledDelegate::onEditFinished()
{
	QWidget *editor = qobject_cast<QWidget *>(sender());
	emit commitData(editor);
	emit closeEditor(editor);
}

 

#pragma once

#include <QWidget>
#include <QPushButton>
#include <QHBoxLayout>
#include "CLineEdit.h"

class MyEditor  : public QWidget
{
	Q_OBJECT

public:
	MyEditor(QWidget *parent);
	~MyEditor();
	QString text() const;
	void setText(const QString &text);
protected:
	virtual void keyPressEvent(QKeyEvent *event) override;
	virtual void focusInEvent(QFocusEvent *event) override;
	virtual void focusOutEvent(QFocusEvent *event) override;
	virtual bool eventFilter(QObject*obj, QEvent*ev) override;
signals:
	void editFinished();

private:
	CLineEdit* m_edit;
	QPushButton* m_btn;
};
#include "MyEditor.h"

MyEditor::MyEditor(QWidget *parent)
	: QWidget(parent)
{
	m_edit = new CLineEdit(this);
	m_btn = new QPushButton(this);
	QHBoxLayout *pLayout = new QHBoxLayout;
	pLayout->addWidget(m_edit);
	pLayout->addWidget(m_btn, 0, Qt::AlignVCenter);
	pLayout->setSpacing(0);
	pLayout->setContentsMargins(0, 0, 0, 0);
	setLayout(pLayout);
	m_edit->installEventFilter(this);
	m_edit->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
	m_btn->setText("...");
	m_btn->setFixedWidth(20);
	m_btn->installEventFilter(this);
	connect(m_edit, SIGNAL(editFinished()), this, SIGNAL(editFinished()));
}

MyEditor::~MyEditor()
{}

QString MyEditor::text() const
{
	return m_edit->text();
}

void MyEditor::setText(const QString & text)
{
	m_edit->setText(text);
	m_edit->setFocus();
}

void MyEditor::keyPressEvent(QKeyEvent *event)
{
	m_edit->setFocus();
	return m_edit->keyPressEvent(event);
}

void MyEditor::focusInEvent(QFocusEvent * event)
{
	m_edit->setFocus();
	return QWidget::focusInEvent(event);
}

void MyEditor::focusOutEvent(QFocusEvent * event)
{
	auto focusWidget = QApplication::focusWidget();
	if (focusWidget == m_btn || focusWidget == this)
		return;
	return QWidget::focusOutEvent(event);
}

bool MyEditor::eventFilter(QObject * obj, QEvent * event)
{
	auto type = event->type();
	if (obj == m_edit)
	{
		auto focusWidget = QApplication::focusWidget();
		if (type == QEvent::FocusOut)
		{
			if (focusWidget == m_btn || focusWidget == this)
				return true;
		}
	}
	return QWidget::eventFilter(obj, event);
}
#pragma once

#include <QLineEdit>
#include <QlistView>
#include <QStringListModel>
#include <QStringList>
#include <QKeyEvent>
#include <QApplication>

class CLineEdit  : public QLineEdit
{
	Q_OBJECT

public:
	CLineEdit(QWidget *parent);
	~CLineEdit();
	void setCompleteData(const QStringList& data);
	void setCompletePrefix(const QString& prefix);
	void showList();
	void hideList();
	void setListWidth(int w);
	void setListHeight(int h);
	bool isListVisiable();

public slots:
	void onCursorPositionChanged(int, int);
	void onTextChanged(const QString&);
	void completeText(const QModelIndex&);

public:
	virtual bool eventFilter(QObject *obj, QEvent *event);
	virtual void keyPressEvent(QKeyEvent *event);
	virtual void focusInEvent(QFocusEvent *event);
	virtual void focusOutEvent(QFocusEvent *event);
	virtual void mouseDoubleClickEvent(QMouseEvent *event);

signals:
	void editFinished();

private:
	QListView*			m_listView;		//补全列表视图
	QStringListModel*	m_listModel;	//补全列表模型
	QStringList			m_listData;		//补全数据
};
#include "CLineEdit.h"

CLineEdit::CLineEdit(QWidget *parent)
	: QLineEdit(parent)
{
	m_listModel = new QStringListModel(this);
	m_listView = new QListView(this);
	m_listView->setModel(m_listModel);
	m_listView->setWindowFlags(Qt::ToolTip);
	m_listView->installEventFilter(this);
	m_listView->setStyleSheet("QListView::item:selected {background-color: rgb(51,153,255); color: white;}");
	m_listView->hide();
	connect(m_listView, SIGNAL(doubleClicked(const QModelIndex&)), this, SLOT(completeText(const QModelIndex&)));
	connect(this, SIGNAL(textChanged(const QString&)), this, SLOT(onTextChanged(const QString&)));
	connect(this, SIGNAL(cursorPositionChanged(int, int)), this, SLOT(onCursorPositionChanged(int, int)));
	//test...
	setCompleteData({ "aa", "aab", "aabc", "aabcd" });
}

CLineEdit::~CLineEdit()
{}

void CLineEdit::setCompleteData(const QStringList& data)
{
	m_listData = data;
}

void CLineEdit::setCompletePrefix(const QString& prefix)
{
	QStringList list;
	if (prefix != ".")
	{
		for (QString data : m_listData)
		{
			if (data.startsWith(prefix, Qt::CaseInsensitive))
				list << data;
		}
	}
	else
	{
		list = m_listData;
	}
	m_listModel->removeRows(0, m_listModel->rowCount());
	m_listModel->setStringList(list);
	showList();
}

void CLineEdit::showList()
{
	if (m_listView->isVisible())
		return;
	int rowCount = m_listModel->rowCount();
	if (rowCount == 0 || text().isEmpty())
		return;
	setListHeight(rowCount * 20);
	int h = height();
	m_listView->move(mapToGlobal(QPoint(0, height())));
	m_listView->show();
}

void CLineEdit::hideList()
{
	m_listView->hide();
}

void CLineEdit::setListWidth(int w)
{
	m_listView->setFixedWidth(w);
}

void CLineEdit::setListHeight(int h)
{
	if (h < 50)
		h = 50;
	if (h > 200)
		h = 200;
	m_listView->setFixedHeight(h);
}

bool CLineEdit::isListVisiable()
{
	return m_listView->isVisible();
}

void CLineEdit::onCursorPositionChanged(int oldPos, int newPos)
{
	QString txt = text();
	if (newPos >= txt.length())
		return;
	txt = txt.mid(0, newPos);
	onTextChanged(txt);
}

void CLineEdit::onTextChanged(const QString& text)
{
	if (text.isEmpty())
	{
		hideList();
		return;
	}
	setCompletePrefix(text);
}

void CLineEdit::completeText(const QModelIndex& index)
{
	QString allText = text();
	QString selectedText = index.data().toString();
	if (selectedText.isEmpty())
	{
		hideList();
		return;
	}
	int cursorPos = cursorPosition();
	QString rightText = allText.mid(cursorPos);
	int pos = allText.lastIndexOf(QRegExp("[ .]"), cursorPos - 1);
	if (pos != -1 && !selectedText.isEmpty())
	{
		QString leftText = allText.left(pos + 1);
		setText(leftText + selectedText + rightText);
	}
	else if (!selectedText.isEmpty())
	{
		setText(selectedText + rightText);
	}
	else
	{
		setText(allText);
	}
	hideList();
}

bool CLineEdit::eventFilter(QObject *obj, QEvent *event)
{
	if (obj == m_listView)
	{
		if (event->type() == QEvent::KeyPress)
		{
			keyPressEvent((QKeyEvent*)event);
			return true;
		}
		if (event->type() == QEvent::FocusOut)
		{
			if(!m_listView->isHidden())
			{
				QPoint pos = cursor().pos();
				if (m_listView->frameGeometry().contains(pos))
					return true;
				QModelIndex currentIndex = m_listView->currentIndex();
				completeText(currentIndex);
			}
			emit editFinished();
		}
	}
	return QLineEdit::eventFilter(obj, event);
}

void CLineEdit::keyPressEvent(QKeyEvent *event)
{
	if (!m_listView->isHidden())
	{
		int key = event->key();
		QModelIndex currentIndex = m_listView->currentIndex();
		if (Qt::Key_Down == key)
		{
			int row = currentIndex.row() + 1;
			QModelIndex index = m_listView->model()->index(row, 0);
			m_listView->setCurrentIndex(index);
		}
		else if (Qt::Key_Up == key)
		{
			int row = currentIndex.row() - 1;
			QModelIndex index = m_listView->model()->index(row, 0);
			m_listView->setCurrentIndex(index);
		}
		else if (Qt::Key_Enter == key || Qt::Key_Return == key)
		{
			completeText(currentIndex);
		}
		else
		{
			hideList();
			QLineEdit::keyPressEvent(event);
		}
	}
	else
	{
		QLineEdit::keyPressEvent(event);
	}
}

void CLineEdit::focusInEvent(QFocusEvent *event)
{
	QLineEdit::focusInEvent(event);
}

void CLineEdit::focusOutEvent(QFocusEvent *event)
{
	if (!m_listView->isHidden())
	{
		QPoint pos = cursor().pos();
		if (m_listView->frameGeometry().contains(pos))
			return;
		QModelIndex currentIndex = m_listView->currentIndex();
		completeText(currentIndex);
	}
	emit editFinished();
	QLineEdit::focusOutEvent(event);
}

void CLineEdit::mouseDoubleClickEvent(QMouseEvent *event)
{
	QLineEdit::mouseDoubleClickEvent(event);
}
#pragma once

#include <QtWidgets/QWidget>
#include "ui_Test1.h"
#include "MyStyledDelegate.h"

class Test1 : public QWidget
{
    Q_OBJECT

public:
    Test1(QWidget *parent = nullptr);
    ~Test1();
protected slots:
	void onItemDoubleClicked(QTreeWidgetItem *item, int column);
private:
    Ui::Test1Class ui;
	MyStyledDelegate *m_delegate = nullptr;
};
#include "Test1.h"

Test1::Test1(QWidget *parent)
    : QWidget(parent)
{
    ui.setupUi(this);

	m_delegate = new MyStyledDelegate(this);
	connect(ui.treeWidget, &QTreeWidget::itemDoubleClicked, this, &Test1::onItemDoubleClicked);
}

Test1::~Test1()
{}

void Test1::onItemDoubleClicked(QTreeWidgetItem *item, int column)
{
	item->setFlags(item->flags() | Qt::ItemIsEditable);
	ui.treeWidget->setItemDelegateForColumn(column, m_delegate);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/706032.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

韩顺平0基础学java——第22天

p441-459 异常exception 选中代码块&#xff0c;快捷键ctraltt6&#xff0c;即trt-catch 如果进行了异常处理&#xff0c;那么即使出现了异常&#xff0c;但是会继续执行 程序过程中发生的异常事件分为两大类&#xff1a; 异常体系图※ 常见的运行异常&#xff1a;类型转换…

继承深度剖析

前言 从继承开始就开始C进阶了&#xff0c; 这一块需要好好学习&#xff0c;这块知识很重要&#xff0c; 坑有点多&#xff0c;所以是面试笔试的常客。 基本概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c; 它允许程序员在保持原有…

使用MNIST数据集训练手写数字识别模型

一、MNIST数据集介绍 MNIST 数据集&#xff08;手写数字数据集&#xff09;是一个公开的公共数据集&#xff0c;任何人都可以免费获取它。目前&#xff0c;它已经是一个作为机器学习入门的通用性特别强的数据集之一&#xff0c;所以对于想要学习机器学习分类的、深度神经网络分…

抓包工具 Wireshark 的下载、安装、使用、快捷键

目录 一、什么是Wireshark&#xff1f;二、Wireshark下载三、Wireshark安装四、Wireshark使用4.1 基本使用4.2 过滤设置1&#xff09;捕获过滤器2&#xff09;显示过滤器 4.3 过滤规则1&#xff09;捕获过滤器-规则语法2&#xff09;显示过滤器-规则语法 4.4 常用的显示过滤器规…

js实现一个数据结构——栈

栈的概念就不再赘述&#xff0c;无可厚非的先进后出&#xff0c;而JS又是高级语言&#xff0c;数组中的方法十分丰富&#xff0c;已经自带了push pop方法进行入栈出栈的操作。 1.基本实现 class Stack {constructor() {this.items [];}// 入栈push(item) {this.items.push(i…

【C++入门(1)】命名空间

一、C出世 我们先简单认识下C的来历&#xff0c;C是在C语言的基础上发展来的。 当年C的设计者Bjarne Stroustrup&#xff0c;本贾尼斯特劳斯特卢普先生设计C语言之初&#xff0c;是为了对C语言做出一些更改&#xff0c;弥补C语言在一些方面的不足&#xff0c;或者做出其他的设…

二阶段提交(2pc)协议

二阶段提交&#xff08;2pc&#xff09;协议 1、 简介 二阶段提交算法是一个分布式一致性算法&#xff0c;强一致、中心化的原子提交协议&#xff0c;主要用来解决分布式事务问题。在单体spring应用中我们往往通过一个Transactional注解就可以保证方法的事务性&#xff0c;但…

破解发展难题 台山这家合作社以农业社会化服务助推乡村振兴

风吹稻田千层浪&#xff0c;眼下&#xff0c;台山四九镇的早稻长势喜人&#xff0c;沉甸甸的稻穗迎风而动&#xff0c;已进入破口抽穗的关键期&#xff0c;即将在6月底陆续迎来丰收。在台山市明华汇种养专业合作社管理的稻田里&#xff0c;合作社负责人梁明喜正仔细观察着稻苗的…

算法第六天:力扣第977题有序数组的平方

一、977.有序数组的平方的链接与题目描述 977. 有序数组的平方的链接如下所示&#xff1a;https://leetcode.cn/problems/squares-of-a-sorted-array/description/https://leetcode.cn/problems/squares-of-a-sorted-array/description/ 给你一个按 非递减顺序 排序的整数数组…

#慧眼识模每日PK[话题]##用五种语言说爸爸我爱你[话题]#

#慧眼识模每日PK #用五种语言说爸爸我爱你 你觉得哪个模型回答得更好&#xff1f;欢迎留言 A.蓝 B.紫 更多问题&#xff0c;扫码体验吧&#xff5e; by 国家&#xff08;杭州&#xff09;新型交换中心

Whisper语音识别 -- 自回归解码分析

前言 Whisper 是由 OpenAI 开发的一种先进语音识别系统。它采用深度学习技术&#xff0c;能够高效、准确地将语音转换为文本。Whisper 支持多种语言和口音&#xff0c;并且在处理背景噪音和语音变异方面表现出色。其广泛应用于语音助手、翻译服务、字幕生成等领域&#xff0c;为…

鸿蒙轻内核A核源码分析系列七 进程管理 (3)

本文记录下进程相关的初始化函数&#xff0c;如OsSystemProcessCreate、OsProcessInit、OsProcessCreateInit、OsUserInitProcess、OsDeInitPCB、OsUserInitProcessStart等。 1、LiteOS-A内核进程创建初始化通用函数 先看看一些内部函数&#xff0c;不管是初始化用户态进程还…

收银系统小程序商城商品详情页再升级!

本期导读 1.新增&#xff1a;商品详情页新增商品参数模块&#xff1b; 2.新增&#xff1a;商品详情页新增保障服务模块&#xff1b; 3.新增&#xff1a;线上商城商品新增划线价&#xff1b; 4.新增&#xff1a;线上商城分销商品新增“赚”字标签及预收收益&#xff1b; 5.…

Linux-笔记 全志平台OTG虚拟 串口、网口、U盘笔记

前言&#xff1a; 此文章方法适用于全志通用平台&#xff0c;并且三种虚拟功能同一时间只能使用一个&#xff0c;原因是此3种功能都是内核USB Gadget precomposed configurations的其中一个选项&#xff0c;只能单选&#xff0c;不能多选&#xff0c;而且不能通过修改配置文件去…

我的考研经历

当我写下这篇文章时&#xff0c;我已经从考研 的失败中走出来了&#xff0c;考研的整个过程都写在博客日志里面了&#xff0c;在整理并阅读考研的日志时&#xff0c;想写下一篇总结&#xff0c;也算是为了更好的吸取教训。 前期日志模板&#xff1a;时间安排的还算紧凑&#x…

安鸾学院靶场——安全基础

文章目录 1、Burp抓包2、指纹识别3、压缩包解密4、Nginx整数溢出漏洞5、PHP代码基础6、linux基础命令7、Mysql数据库基础8、目录扫描9、端口扫描10、docker容器基础11、文件类型 1、Burp抓包 抓取http://47.100.220.113:8007/的返回包&#xff0c;可以拿到包含flag的txt文件。…

DDei在线设计器-配置主题风格

DDeiCore-主题 DDei-Core插件提供了默认主题和黑色主题。 如需了解详细的API教程以及参数说明&#xff0c;请参考DDei文档 默认主题 黑色主题 使用指南 引入 import { DDeiCoreThemeBlack } from "ddei-editor";使用并修改设置 extensions: [......//通过配置&am…

【FreeRTOS】内存管理

目录 1 为什么要自己实现内存管理2 FreeRTOS的5中内存管理方法2.1 Heap_12.2 Heap_22.3 Heap_32.4 Heap_4 2.5 Heap_53 Heap相关的函数3.1 pvPortMalloc/vPortFree3.2 xPortGetFreeHeapSize 3.3 xPortGetMinimumEverFreeHeapSize3.4 malloc失败的钩子函数 参考《FreeRTOS入门与…

Python私教张大鹏 Vue3整合AntDesignVue之DatePicker 日期选择框

案例&#xff1a;选择日期 <script setup> import {ref} from "vue";const date ref(null) </script> <template><div class"p-8 bg-indigo-50 text-center"><a-date-picker v-model:value"date"/><a-divide…