首页 > 其他分享 >Qt自定义TreeWidget,实现展开折叠按钮在右侧,且一条竖直线上对齐

Qt自定义TreeWidget,实现展开折叠按钮在右侧,且一条竖直线上对齐

时间:2024-08-10 12:53:27浏览次数:11  
标签:pItem Qt 自定义 void QTreeWidgetItem treeWidget TreeWidget CCustomTreeWidget pPushB

效果如下:

图片随便找的,可能需要调下样式,代码复制可用,留给有需要的人。 

#ifndef CustomTreeWidget_h__
#define CustomTreeWidget_h__

#include <QTreeWidget>
#include <QPushButton>

class CCustomTreeWidget : public QTreeWidget
{
	Q_OBJECT

public:
	CCustomTreeWidget(QWidget* parent = nullptr);
	~CCustomTreeWidget();

	QTreeWidgetItem* AddItem(QTreeWidgetItem* pParent = NULL);

	void ToggleItem(QTreeWidgetItem* pItem);

	void ExpandAllNodes();

	void CollapseAllNodes();

protected:

	void mousePressEvent(QMouseEvent* event) override;

	void keyPressEvent(QKeyEvent* event) override;

private:

	void UpdateItemWidget(QTreeWidgetItem* pItem);

	void UpdateAllButtons(const QIcon& icon);

	void UpdateItemButton(QTreeWidgetItem* pItem, const QIcon& icon);

private slots:

	void SlotToggleNode(QTreeWidgetItem* pItem, QPushButton* pPushButton);

};

#endif // CustomTreeWidget_h__
#include "CustomTreeWidget.h"
#include <QHeaderView>
#include <QMouseEvent>
#include <QBoxLayout>

CCustomTreeWidget::CCustomTreeWidget(QWidget* parent /*= nullptr*/)
	: QTreeWidget(parent)
{
	setAttribute(Qt::WA_TranslucentBackground, true);

	setRootIsDecorated(false);

	setColumnCount(2);

	header()->hide();
	header()->setSectionResizeMode(0, QHeaderView::ResizeToContents); // 第一列宽度自适应内容
	header()->setSectionResizeMode(1, QHeaderView::Fixed); // 第二列宽度固定
	setColumnWidth(1, 30); // 设置一个初始宽度,实际宽度会在按钮创建后更新

	// 隐藏默认的展开和折叠按钮
	setStyleSheet("QTreeView::branch:has-children:!has-siblings:closed,"
		"QTreeView::branch:closed:has-children:has-siblings {"
		"border-image: none; image: none;}"
		"QTreeView::branch:open:has-children:!has-siblings,"
		"QTreeView::branch:open:has-children:has-siblings {"
		"border-image: none; image: none;}"
		"QTreeWidget::item{ height: 20px; }");
}

CCustomTreeWidget::~CCustomTreeWidget()
{

}

QTreeWidgetItem* CCustomTreeWidget::AddItem(QTreeWidgetItem* pParent)
{
	QTreeWidgetItem* pItem = NULL;
	if (NULL != pParent)
	{
		pItem = new QTreeWidgetItem(pParent);
		pParent->addChild(pItem);

		UpdateItemWidget(pParent);
	}
	else
	{
		pItem = new QTreeWidgetItem();

		addTopLevelItem(pItem);

		UpdateItemWidget(pItem);
	}

	return pItem;
}

void CCustomTreeWidget::ToggleItem(QTreeWidgetItem* pItem)
{
	if (NULL == pItem)
	{
		return;
	}

	if (NULL != itemWidget(pItem, 1))
	{
		QPushButton* pPushButton = qobject_cast<QPushButton*>(itemWidget(pItem, 1)->findChild<QPushButton*>());
		if (pItem->isExpanded())
		{
			pPushButton->setIcon(QIcon(":/treeitem-expanded.png"));
		}
		else
		{
			pPushButton->setIcon(QIcon(":/treeitem-collapsed.png"));
		}
	}
}

void CCustomTreeWidget::ExpandAllNodes()
{
	expandAll();
	UpdateAllButtons(QIcon(":/treeitem-expanded.png"));
}

void CCustomTreeWidget::CollapseAllNodes()
{
	collapseAll();
	UpdateAllButtons(QIcon(":/treeitem-collapsed.png"));
}

void CCustomTreeWidget::mousePressEvent(QMouseEvent* event)
{
	if (itemAt(event->pos()))
	{
		event->accept();
	}
	else
	{
		QTreeWidget::mousePressEvent(event);
	}
}

void CCustomTreeWidget::keyPressEvent(QKeyEvent* event)
{
	if (event->key() == Qt::Key_Right || event->key() == Qt::Key_Left)
	{
		event->ignore();
	}
	else
	{
		QTreeWidget::keyPressEvent(event);
	}
}

void CCustomTreeWidget::UpdateItemWidget(QTreeWidgetItem* pItem)
{
	if (NULL == pItem)
	{
		return;
	}

	if (pItem->childCount() > 0)
	{
		QWidget* pWidget = new QWidget();
		QHBoxLayout* pLayout = new QHBoxLayout(pWidget);
		pLayout->setContentsMargins(0, 0, 0, 0);
		pLayout->setAlignment(Qt::AlignRight);

		QPushButton* pPushButton = new QPushButton();
		pPushButton->setStyleSheet("background: transparent; border: none;");
		QIcon icon(":/treeitem-collapsed.png");
		pPushButton->setIcon(icon);
		pPushButton->setIconSize(icon.availableSizes().first());
		pLayout->addWidget(pPushButton);

		pWidget->setLayout(pLayout);
		setItemWidget(pItem, 1, pWidget);

		const int nIconWidth = pPushButton->iconSize().width();
		setColumnWidth(1, nIconWidth);

		connect(pPushButton, &QPushButton::clicked, [this, pItem, pPushButton]()
		{
			SlotToggleNode(pItem, pPushButton);
		});
	}
	else
	{
		if (QWidget* pWidget = itemWidget(pItem, 1))
		{
			delete pWidget;
			setItemWidget(pItem, 1, NULL);
		}
	}
}

void CCustomTreeWidget::UpdateAllButtons(const QIcon& icon)
{
	for (int i = 0; i < topLevelItemCount(); ++i)
	{
		UpdateItemButton(topLevelItem(i), icon);
	}
}

void CCustomTreeWidget::UpdateItemButton(QTreeWidgetItem* pItem, const QIcon& icon)
{
	if (NULL != itemWidget(pItem, 1))
	{
		QPushButton* pPushButton = qobject_cast<QPushButton*>(itemWidget(pItem, 1)->findChild<QPushButton*>());
		if (NULL != pPushButton)
		{
			pPushButton->setIcon(icon);
		}

		for (int i = 0; i < pItem->childCount(); ++i)
		{
			UpdateItemButton(pItem->child(i), icon);
		}
	}
}

void CCustomTreeWidget::SlotToggleNode(QTreeWidgetItem* pItem, QPushButton* pPushButton)
{
	if (pItem->isExpanded())
	{
		pItem->setExpanded(false);
		pPushButton->setIcon(QIcon(":/treeitem-collapsed.png"));
	}
	else
	{
		pItem->setExpanded(true);
		pPushButton->setIcon(QIcon(":/treeitem-expanded.png"));
	}
}

调用代码:

#include "CustomTreeWidget.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
	CCustomTreeWidget treeWidget;
	treeWidget.setWindowTitle("Custom Tree Widget");
	treeWidget.resize(400, 300);

	// 添加三个顶级节点
	QTreeWidgetItem* topLevelItem1 = treeWidget.AddItem();
	topLevelItem1->setText(0, "Top Level 1");

	QTreeWidgetItem* topLevelItem2 = treeWidget.AddItem();
	topLevelItem2->setText(0, "Top Level 2");

	QTreeWidgetItem* topLevelItem3 = treeWidget.AddItem();
	topLevelItem3->setText(0, "Top Level 3");

	// 为每个顶级节点增加三级子节点
	for (int i = 0; i < 3; ++i)
	{
		QTreeWidgetItem* child1 = treeWidget.AddItem(topLevelItem1);
		child1->setText(0, QString("Child 1.%1").arg(i + 1));

		QTreeWidgetItem* child2 = treeWidget.AddItem(topLevelItem2);
		child2->setText(0, QString("Child 2.%1").arg(i + 1));

		QTreeWidgetItem* child3 = treeWidget.AddItem(topLevelItem3);
		child3->setText(0, QString("Child 3.%1").arg(i + 1));

		for (int j = 0; j < 3; ++j)
		{
			QTreeWidgetItem* grandChild1 = treeWidget.AddItem(child1);
			grandChild1->setText(0, QString("Grandchild 1.%1.%2").arg(i + 1).arg(j + 1));

			QTreeWidgetItem* grandChild2 = treeWidget.AddItem(child2);
			grandChild2->setText(0, QString("Grandchild 2.%1.%2").arg(i + 1).arg(j + 1));

			QTreeWidgetItem* grandChild3 = treeWidget.AddItem(child3);
			grandChild3->setText(0, QString("Grandchild 3.%1.%2").arg(i + 1).arg(j + 1));
		}
	}

	treeWidget.show();
    return a.exec();
}

标签:pItem,Qt,自定义,void,QTreeWidgetItem,treeWidget,TreeWidget,CCustomTreeWidget,pPushB
From: https://blog.csdn.net/m0_59119702/article/details/141070887

相关文章

  • 【QT】Qt 音视频
    Qt音视频Qt音视频1.Qt音频2.Qt视频Qt音视频在Qt中,音频主要是通过QSound类来实现。但是需要注意的是QSound类只支持播放wav格式的音频文件。也就是说如果想要添加音频效果,那么首先需要将非wav格式的音频文件转换为wav格式。通过帮助手册查看QSo......
  • 一个简单的录音软件(利用QT录音,ffmpeg进行音频重采样,fdk-aac编码)
             录音软件是一种非常有用的工具,可以帮助我们记录和存储语音信息。在本文中,我们将介绍一个简单的录音软件,该软件利用QT进行录音,使用ffmpeg进行音频重采样,并使用fdk-aac编码。一、 环境介绍  1、QT版本:QT5.12.62、编译器: MSVC2017643、ffmpeg版......
  • 利用QT和FFmpeg实现一个简单的视频播放器
              在当今的多媒体世界中,视频播放已成为不可或缺的一部分。从简单的媒体播放器到复杂的视频编辑软件,视频解码和显示技术无处不在。本示例使用Qt和FFmpeg构建一个简单的视频播放器。利用ffmpeg解码视频,通过QWidget渲染解码后的图像,支持进度条跳转、进度条显示,......
  • linux自定义启动服务
    启动程序你需要分清楚,是一般的程序还是服务对于有些服务开机要启动,关机的时候还要关闭,所以,比较好的方法是写服务脚本,然后放到/etc/init.d,然后在相应的运行级启动目录中添加链接。如果只是一般的程序,并且关机时不需要退出。那么加在任何一个自启动的脚本都可以。下面结合condor启......
  • 自定义类型:结构体
    文章目录结构体结构体定义和声明结构体的初始化和赋值对结构体类型名的优化结构体的自引用与嵌套结构体访问与操作匿名结构体结构体中的内存对齐(面试常考)计算结构体字节大小对齐规则为什么存在内存对齐?修改默认对齐数结构体传参结构体实现位段位段的内存分配位段跨平......
  • systemctl 如何自定义添加服务
    创建一个服务文件:在/etc/systemd/system/目录下创建一个以.service结尾的文件,比如myservice.service[Unit]Description=MyServiceAfter=network.target[Service]ExecStart=/path/to/your/service/executableWorkingDirectory=/path/to/your/service/directoryUser=......
  • mqtt订阅和发布
    importpaho.mqtt.clientasmqttimporttimeMQTTHOST="192.168.0.4"MQTTPORT=1883mqttClient=mqtt.Client()#连接MQTT服务器defon_mqtt_connect():mqttClient.connect(MQTTHOST,MQTTPORT,60)mqttClient.loop_start()#publish消息defon_publish(t......
  • 自定义周选择组件、年选择组件
    //周组件weekSelect<!--周选择组件--><template><divref="viYearSelect"class="vi-year-select"><ui-inputv-model="selectVal":placeholder="placeholder":d......
  • 博客园自定义皮肤工具推荐:awescnb
    简介awescnb是一个用于博客园(Cnblogs)的自定义皮肤和功能增强插件。它允许用户通过简单的配置来自定义其博客的外观和增加一些额外的功能。下面是对awescnb的简要介绍:功能特点:自定义皮肤:用户可以选择不同的皮肤主题,包括背景颜色、字体样式等,以个性化他们的博客页面。扩展......
  • 【自动驾驶】自定义消息格式的话题通信(C++版本)
    目录新建消息文件更改包xml文件中的依赖关系更改cmakelist文件中的配置执行时依赖改变cmakelist编译顺序发布者程序调用者程序程序测试新建消息文件在功能包目录下,新建msg文件夹,下面新建mymsg.msg文件,其内容为stringnamefloat64value发布者包含该消息,生成头文......