当前位置: 首页 > news >正文

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

效果如下:

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

#ifndef CustomTreeWidget_h__
#define CustomTreeWidget_h__#include <QTreeWidget>
#include <QPushButton>class CCustomTreeWidget : public QTreeWidget
{Q_OBJECTpublic: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();
}

相关文章:

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

效果如下&#xff1a; 图片随便找的&#xff0c;可能需要调下样式&#xff0c;代码复制可用&#xff0c;留给有需要的人。 #ifndef CustomTreeWidget_h__ #define CustomTreeWidget_h__#include <QTreeWidget> #include <QPushButton>class CCustomTreeWidget : p…...

硅步千里:如何入行?——之入行成为软件开发者

无论何时&#xff0c;你是否有遇到这样的场景&#xff08;在自己从未涉足过的行业或领域&#xff0c;现在需要自己去这个行业或领域学习探索&#xff0c;最初的目标是熟悉行业&#xff0c;快速融入进去&#xff0c;很多时候&#xff0c;我们只是了解了个大概&#xff0c;并没能…...

Sandbox: rsync.samba(80134) deny(1) file-write-create

Xcode15运行报错:Sandbox: rsync.samba(80134) deny(1) file-write-create/xxx/xxx 如下图: 解决办法: Build Settings 搜索 sandbox&#xff0c;把 Build Options 中的 User Script Sandboxing改为 NO...

lvs的dr模式综合实践

目录 ​编辑虚拟机准备工作 ​编辑​编辑​编辑 配置过程 配置client主机 配置router主机 配置lvs主机&#xff08;vip使用环回来创建&#xff09; 配置server1主机&#xff08;vip使用环回来创建&#xff09; 配置server2主机&#xff08;vip使用环回来创建&#xff0…...

什么是自然语言处理

自然语言处理&#xff08;Natural Language Processing, NLP&#xff09;是人工智能&#xff08;AI&#xff09;的一个子领域&#xff0c;涉及计算机与人类语言的交互。它的目标是让计算机能够理解、分析、生成和操作自然语言&#xff0c;从而实现与人类的有效沟通。 自然语言处…...

快速理解互联网中的常用名词

并发与并行 并发&#xff1a;任务交替执行&#xff0c;伪并行&#xff0c;涉及CPU时间片和上下文切换。并行&#xff1a;任务真正同时执行&#xff0c;需要多核处理器&#xff0c;无上下文切换。 并发量&#xff08;Concurrency&#xff09; 概念&#xff1a;服务端程序单位…...

统计接口调用耗时_黑白名单配置

黑名单配置 黑名单就是那些被禁止访问的URL创建自定义过滤器 BlackListUrlFilter&#xff0c;并配置黑名单地址列表blacklistUrl如果有其他需求&#xff0c;还可以实现自定义规则的过滤器来满足特定的过滤要求 /*** 黑名单过滤器** author canghe*/ Component public class B…...

树莓派4 AV没有视频输出

使用AV接口输出&#xff0c;没有画面 需要在config.txt文件中 增加配置 enable_tvout1config.txt 中的 dtoverlayvc4-kms-v3d 行末尾添加,composite&#xff1a; dtoverlayvc4-kms-v3d,composite默认情况下&#xff0c;输出 NTSC 复合视频。要选择不同的模式&#xff0c;请在…...

短信群发平台:解决短信验证码接收问题的5大策略

在享受数字化服务时&#xff0c;如APP注册或网站登录&#xff0c;若遇到短信验证码无法接收的困扰&#xff0c;无疑会增添不少烦恼。为了帮助您迅速解决这一问题&#xff0c;我们精心总结了以下十大原因及对应的解决方法&#xff0c;助您顺畅完成验证流程。 一、优化网络环境 …...

WebSocket 初体验:构建实时通信应用

WebSocket是一种在客户端和服务器之间建立持久连接的协议&#xff0c;它允许双方进行双向通信&#xff0c;从而实现低延迟的数据交换。WebSocket非常适合需要实时交互的应用场景&#xff0c;比如聊天应用、在线游戏、实时数据分析等。 WebSocket简介 什么是WebSocket&#xf…...

LISA: Reasoning Segmentation via Large Language Model

发表时间&#xff1a;CVPR 2024 论文链接&#xff1a;https://openaccess.thecvf.com/content/CVPR2024/papers/Lai_LISA_Reasoning_Segmentation_via_Large_Language_Model_CVPR_2024_paper.pdf 作者单位&#xff1a;CUHK Motivation&#xff1a;尽管感知系统近年来取得了显…...

企业发展与数字化转型:创新驱动未来增长的关键策略

引言 在当今全球化和信息化高度融合的时代&#xff0c;数字化转型已经成为企业寻求增长和保持竞争优势的关键战略。随着技术的飞速进步&#xff0c;数字化不仅改变了商业模式和市场格局&#xff0c;还深刻影响了企业的内部运作和外部生态系统。大数据、人工智能、物联网等新兴技…...

如何选择适合自己的编程语言,为什么R是非计算机专业数据分析的最佳选择,五大点告诉你

在如今的数据驱动世界中&#xff0c;编程语言已成为希望在行业中进行数据分析的专业人士不可或缺的技能。对于非计算机专业背景的学者和学生来说&#xff0c;选择适合自己的编程语言可能看似困难。本文将探讨为什么对于那些需要进行本科生论文、研究生论文、或者发表学术成果的…...

【经验分享】数据结构——求树的叶子结点个数计算方法

目录 一道题就可以学会 这种题做法固定&#xff0c;记住两个公式即可 解惑&#xff1a; 1、为什么n2010110x&#xff1f; 2、为什么是n-120*410*31*210*1x*0&#xff1f; &#x1f308; 嗨&#xff0c;我是命运之光&#xff01; &#x1f30c; 2024&#xff0c;每日百字&…...

第十一章:图论part04 110.字符串接龙 105.有向图的完全可达性 106.岛屿的周长(补)

任务日期&#xff1a;7.29 题目一链接&#xff1a;110. 字符串接龙 (kamacoder.com) 思路&#xff1a;将本题寻找附近的字符串等效于寻找四周的陆地&#xff0c;即寻找周围与当前字符只有一位不同的字符串&#xff0c;然后加入到队列中并标记上&#xff0c;在此基础上要将字符…...

Linux中安装MYSQL数据库

文章目录 一、MYSQL数据库介绍1.1、MySQL数据库的基本概述1.2、MySQL数据库的主要特性1.3、MySQL数据库的技术架构与组件1.4、MySQL数据库的应用与扩展性1.5、MySQL数据库的许可模式与开源生态 二、MySQL Workbench和phpMyAdmin介绍2.1、MySQL Workbench介绍2.2、phpMyAdmin介绍…...

Vue前端服务加密后端服务解密--AES算法实现

在实际项目中考虑到用户数据的安全性&#xff0c;在用户登录时&#xff0c;前端需要对用户密码加密&#xff08;防止用户密码泄露&#xff09;&#xff0c;服务端收到登录请求时先对密码进行解密&#xff0c;然后再进行用户验证登操作。本文使用 AES ECB 模式算法来实现前端机密…...

matlab实现文字识别

在MATLAB中实现文字识别通常涉及图像处理技术和机器学习算法&#xff0c;特别是使用MATLAB内置的Image Processing Toolbox和Machine Learning Toolbox。下面是一个基本的步骤指南&#xff0c;展示如何在MATLAB中设置和执行一个简单的OCR&#xff08;Optical Character Recogni…...

Leetcode - 周赛409

目录 一&#xff0c;3242. 设计相邻元素求和服务 二&#xff0c;3243. 新增道路查询后的最短距离 I 三&#xff0c;3244. 新增道路查询后的最短距离 II 四&#xff0c;3245. 交替组 III 一&#xff0c;3242. 设计相邻元素求和服务 本题纯模拟&#xff0c;代码如下&#xff…...

突破百度网盘的下载限速,两种方法教会你【超详细】

一、前言 Hello&#xff0c;大家后&#xff0c;我是博主英杰&#xff0c;前几天&#xff0c;我在使用百度网盘过程中&#xff0c;下载速度极慢&#xff0c;自己作为一个白嫖党&#xff0c;开会员也是心疼那点钱&#xff0c;所以在网上找了几个有效解决百度网盘限速问题的教程&a…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

基于FPGA的PID算法学习———实现PID比例控制算法

基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容&#xff1a;参考网站&#xff1a; PID算法控制 PID即&#xff1a;Proportional&#xff08;比例&#xff09;、Integral&#xff08;积分&…...

shell脚本--常见案例

1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件&#xff1a; 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

全志A40i android7.1 调试信息打印串口由uart0改为uart3

一&#xff0c;概述 1. 目的 将调试信息打印串口由uart0改为uart3。 2. 版本信息 Uboot版本&#xff1a;2014.07&#xff1b; Kernel版本&#xff1a;Linux-3.10&#xff1b; 二&#xff0c;Uboot 1. sys_config.fex改动 使能uart3(TX:PH00 RX:PH01)&#xff0c;并让boo…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

【Go语言基础【13】】函数、闭包、方法

文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数&#xff08;函数作为参数、返回值&#xff09; 三、匿名函数与闭包1. 匿名函数&#xff08;Lambda函…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...