Qt QTreeWidget节点的添加+双击响应+删除详解

2023-05-16

QTreeWidget是实现树形结构的类,在很多软件中都可以看到类似树形结构的界面。

我做的一个示例如下图,用来处理图像,最顶层节点是图像的路径名,子节点是图像的各个波段,双击各个波段会显示图像各波段的灰度图像,同时还有删除指定节点(父节点和子节点同时删除)的功能。效果如下所示

要完成这样的功能需要注意一下几点:

①.在内存中保存各个节点,当然要在堆上分配内存,删除节点时,除了去除QtreeWidget控件上的节点外,还要讲存储在内存中的节点也要删除,否则会出现内存泄露的问题。

②.节点双击的事件响应,准确定位到是哪个图像的哪个波段。

下面详细叙述。

1.变量

需要有个变量记录图像的路径名,这里定义一个容器,数据类型为QString

QVector<QString> imgFile;

2.定义信号和槽

需要三个槽,

打开菜单:每使用打开菜单打开一幅图像就将该图像的路径名和波段数设计成父节点和子节点添加到QTreeWidget控件中。

删除节点的按钮:删除指定节点(该节点处于高亮状态,即选中状态)

双击某波段:显示该波段的灰度图像。

这里着重讲解与QTreeWidget相关的,因此有关显示图像的内容概不论述。

信号与槽链接如下:

打开菜单      connect(ui.Open,SIGNAL(triggered()),this,SLOT(menu_Open()));

双击某波段   connect(ui.treeWidget,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(showSelectedImg(QTreeWidgetItem*,int)));

删除节点      connect(ui.DeleteNode,SIGNAL(clicked()),this,SLOT(btn_DeleteNode()));

3.打开图像(添加节点)


    imgFile.append(fileName);//影像路径添加进容器
    QTreeWidgetItem *item=new QTreeWidgetItem(ui.treeWidget,QStringList(QString(fileName)));//添加节点
    //添加子节点
    for (int i=0;i<rasterNum;i++)
    {
        QTreeWidgetItem *item1=new QTreeWidgetItem(item,QStringList(QString("Band")+QString::number(i+1)));
        item->addChild(item1);
    }  

其中rasterNum为路径名为fileName的图像的波段数。

这样在QTreewidget部件对象treeWidget中就增加了树节点及其子节点。每次打开都会在树形节点最后面添加。

这里需要提醒一点:这里的QTreewidgetItem指针对象指向的地址都分配在堆上,会不会造成内存泄露呢?因为函数结束后作为局部变量的指针当然是消失了,但保存QTreeWidgetItem节点的内存地址还在,有没有办法在需要的时候将其内存地址释放掉呢,答案是肯定的,将在后面删除节点时论述。

4.双击某波段显示波段图像


        QTreeWidgetItem *parent=item->parent();//获得父节点
    if(NULL==parent)
        return;
    progessBar->setValue(0);//进度条置0
    int row=parent->indexOfChild(item);//获得节点在父节点中的行号(从0开始)
    QString fileName=parent->text(0);//获得父节点的文本字符(即影像路径)
    /* QString->const char* */
    QByteArray ba=fileName.toLocal8Bit();
    const char* filePath=ba.data();  

这里贴出的是找到图像路径和子节点波段的方法,至于显示出图像就是根据图像路径和波段号显示出波段响应灰度图像,该问题不在讨论范畴,略去。

5.删除节点

这里的删除节点不是删除所有节点,而是删除与该节点有关的图像的所有节点,比如,鼠标指向了最开始图中第二个父节点的任意一个子节点,则就将该父节点和所有子节点删除。


    QTreeWidgetItem* item=ui.treeWidget->currentItem();//获得当前节点
    if(NULL==item)//没有选择节点
        return;
    QTreeWidgetItem* parent=item->parent();//获得当前节点的父节点
    int index;//top节点的索引号
    if(NULL==parent)//item就是top节点
    {
        QString fileName=item->text(0);//获得top节点的文本字符(即影像路径)
        for (int i=0;i<imgFile.size();i++)
        {
            if (fileName==imgFile.at(i))
            {
                index=i;
                break;
            }
        }
        ui.treeWidget->takeTopLevelItem(index);//去除节点 Removes the top-level item at the given index in the tree and returns it
        imgFile.remove(index);//移除容器index处内容

        //释放掉存放节点的内存空间
        int childCount=item->childCount();//子节点数
        for (int i=0;i<childCount;i++)
        {
            QTreeWidgetItem* childItem=item->child(0);
            delete childItem;
            childItem=NULL;
        }
        delete item;
        item=NULL;
    }
    else//parent才是top节点
    {
        QString fileName=parent->text(0);//获得top节点的文本字符(即影像路径)
        for (int i=0;i<imgFile.size();i++)
        {
            if (fileName==imgFile.at(i))
            {
                index=i;
                break;
            }
        }
        ui.treeWidget->takeTopLevelItem(index);//去除节点 Removes the top-level item at the given index in the tree and returns it
        imgFile.remove(index);//移除容器index处内容

        //释放掉存放节点的内存空间
        int childCount=parent->childCount();//子节点数
        for (int i=0;i<childCount;i++)
        {
            item=parent->child(0);
            delete item;
            item=NULL;
        }
        delete parent;
        parent=NULL;
    }  

主要方法就是根据图像路径名获得图像在top节点中的索引号,然后将top节点及其子节点删除,采用takeTopLevelItem(index)方法可以把treeWidget中的所因为index的节点去除掉,注意这里只是将节点从treeWidget中去除掉,其节点(父节点+子节点)仍然存在内存中,所以还要讲内存中的地址也要释放掉,否则就会出现所谓的内存泄露的问题。所采用的方法时使用QTreeWidgetItem指针找到存放节点的内存地址,然后将其delete掉,如此就释放掉内存空间了(有疑问的可以跟踪调试下),一定注意将要删除的节点全部delete掉,先释放子节点内存,再释放父节点内存。

还需要注意的是,每清除掉一个子节点的内存空间,对应父节点就会失去该子节点,因此每次都是清理掉父节点索引为0的子节点,即获得child(0)的子节点。此外不要忘了保存图像路径的向量imgFile中也要去除对应的索引内容。

总结

以上给出的是实现功能的核心实现部分,并非完整的程序,其他未论述的都是与QTreeWidget该控件无关的了。上述方法可移植性强,可以用到有类似需求的地方。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt QTreeWidget节点的添加+双击响应+删除详解 的相关文章

  • 技术淘宝

    精度前端学习 前端开发100天 xff08 置顶 xff09 http alloyteam github io CodeGuide https github com AlloyTeam CodeGuide cmd控制台的小技巧 xff1a
  • Migration: Find Duplicate Objects in Application Desinger Projects

    The sql will identify duplicate objects in different application designer projects to eliminate duplicate work by develo
  • SQL server loginname alias mapping problem.

    exec sp changedbowner 39 Aambriore mra 39 EXEC sp change users login 39 Auto Fix 39 39 lts 39 null Exec sp change users
  • [ASP.NET MVC 小牛之路]08 - Area 使用

    ASP NET MVC允许使用 Area xff08 区域 xff09 来组织Web应用程序 xff0c 每个Area代表应用程序的不同功能模块 这对于大的工程非常有用 xff0c Area 使每个功能模块都有各自的文件夹 xff0c 文件
  • OpennVINS运行、评估笔记

    1 安装运行 1 1 下载 amp 编译 span class token builtin class name cd span catkin ws src span class token function git span clone
  • 关于apm飞控烧bootloader

    最近一直由于学校大创申请的的四轴 xff0c 一直在做这玩意 xff0c 哎 xff0c 无奈这货实在不像想象的那样简单 xff0c 自己写了N久飞控 xff0c 也没把飞机飞起来 xff0c 只能先用开源的apm飞控练练手呗 xff0c
  • c语言实现subs指令,周立功LPC系统移植学习之c启动代码修改一

    一 系统移植用c启动代码 Copyright c Guangzou ZLG MCU Development Co LTD graduate school http www zlgmcu com File Info
  • Google开源项目phpdoc-zh【PHP中文手册】

    为什么80 的码农都做不了架构师 xff1f gt gt gt 现在不用愁找不到好的PHP中文手册 xff0c 没乱码 xff0c 更新速度快 xff0c 翻译准确 xff01 项目地址 xff1a http code google com
  • 计算机与我的生活英语作文,描写一天的生活英语作文(通用7篇)

    描写一天的生活英语作文 通用7篇 在平凡的学习 工作 生活中 xff0c 大家都不可避免地要接触到作文吧 xff0c 作文要求篇章结构完整 xff0c 一定要避免无结尾作文的出现 相信很多朋友都对写作文感到非常苦恼吧 xff0c 下面是小编
  • reStructuredText语法简单说明

    reStructuredText 是扩展名为 rst的纯文本文件 xff0c 含义为 34 重新构建的文本 34 34 xff0c 也被简称为 xff1a RST或reST 官方网址 xff1a http docutils sourcefo
  • 优秀的程序员需要擅长数学吗?

    天有很多年轻人或经验不足的程序员 在 论坛发帖 在 Stack Exchange 网站问 xff1a 为了成为优秀的程序员 xff0c 我需要擅长数学吗 xff1f xff0c 在我还年轻的时候 xff0c 我也问自己同样的问题 最近 xf
  • datax同步MySQL数据到mongodb

    根据生产需要 xff0c 同步非实时数据到mongodb 经过同事间的不断研究 xff0c 特弄出了这样一套方案 xff1a MySQL xff08 RDS xff09 gt Datax gt mongodb 我们的mysql用的是阿里云的
  • 网络虚拟化

    网络虚拟化的内容一般指虚拟专用网络 对网络连接的概念进行了抽象 xff0c 允许远程用户访问组织的内部网络 xff0c 就像物理上连接到该网络一样 网络虚拟化可以帮助保护 IT 环境 xff0c 防止来自 Internet 的威胁 xff0
  • C语言实现wake on lan(网络唤醒)

    wake on lan是一种网络唤醒功能 xff0c 它可以实现远程开机 xff0c 刚好实验室有一台ftp服务器 xff0c 因为不是24小时开机的 xff0c 所以每次开机都要跑过去用手按开关 xff0c 非常麻烦 xff0c 于是在网
  • 裸辞2个月,找不到新工作,我这样的程序员多吗?

    如题 xff0c 年后回来毅然决然从公司离职 xff0c 离职一时爽 xff0c 此时心已凉 离职2个月了 xff0c 记不得多久以前已经找不到新公司投简历了 面试机会太少 xff0c 私活太少 快活不起了 像我这样的程序员现在多吗 xff
  • Linux驱动示例

    本文首先描述了一个可以实际测试运行的驱动实例 xff0c 然后由此去讨论Linux下驱动模板的要素 xff0c 以及Linux上应用程序到驱动的执行过程 相信这样由浅入深 由具体实例到抽象理论的描述更容易初学者入手Linux驱动的大门 一
  • 清华裴丹:AIOps 落地路线图

    AIOps概念火热 xff0c 但如何落地 xff1f 清华大学裴丹副教授在GOPS上海站的主题演讲中 xff0c 通过庖丁解牛的方式给出了AIOps落地的技术路线图 xff1b 同时提出AIOps落地战略路线图 xff0c 通过AIOps
  • JS编写冒泡函数

    function Sort arr for var i 61 0 i lt arr lrngth i 43 43 for var j 61 0 j lt arr length i 1 j 43 43 if arr j lt arr j 43
  • 从软件到片源!PC播放HDTV上手全攻略

    高清视界来临 HDTV迅速走红 随着CCTV HD节目的试播开始 xff0c HDTV这个词越来越多的在人们的生活中出现 很多人家里买了HDTV电视 xff0c 但是却感到自己收看到的节目并没有更加清晰 xff0c 甚至效果不如以前 究竟什
  • linux系统日志

    日志记录系统每天发生的各种各样的事情 xff0c 比如监控系统的状况 xff0c 排查系统的故障等 你可以通过日志来检查错误发生的原因 xff0c 或者受到攻击时留下的痕迹 日志的主要功能是审计和监测 xff0c 还有实时的监测系统状态 x

随机推荐