Detailed explanation of Qt QTreeWidget node addition + double-click response + deletion

QTreeWidget is a class that implements a tree structure. Interfaces similar to a tree structure can be seen in many software.

An example I made is as shown below, which is used to process images. The top-level node is the path name of the image, and the child nodes are the various bands of the image. Double-clicking each band will display the grayscale image of each band of the image, and also delete the specified node ( The function of deleting parent nodes and child nodes at the same time). The effect is as follows

To complete such a function, you need to pay attention to the following points:

①. To save each node in memory, of course, allocate memory on the heap. When deleting nodes, in addition to removing the nodes on the QtreeWidget control, the nodes stored in the memory must also be deleted, otherwise memory leaks will occur. .

②. The event response of the node double-click accurately locates which image and which band.

Detailed description below.

1.Variables

There needs to be a variable to record the path name of the image. Here we define a container with the data type QString.

QVector<QString> imgFile;

2. Define signals and slots

Three slots are needed,

Open menu: Every time you use the open menu to open an image, the path name and band number of the image are designed as parent nodes and child nodes and added to the QTreeWidget control.

Button to delete node: delete the specified node (the node is highlighted, that is, selected)

Double-click a band: the grayscale image of the band will be displayed.

The focus here is related to QTreeWidget, so the content about displaying images will not be discussed in summary.

The signals and slots are linked as follows:

Open the menu connect(ui.Open,SIGNAL(triggered()),this,SLOT(menu_Open()));

Double-click a band connect(ui.treeWidget,SIGNAL(itemDoubleClicked(QTreeWidgetItem*,int)),this,SLOT(showSelectedImg(QTreeWidgetItem*,int)));

Delete node connect(ui.DeleteNode,SIGNAL(clicked()),this,SLOT(btn_DeleteNode()));

3. Open the image (add nodes)

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);
    }

Where rasterNum is the number of bands of the image with the path name fileName.

In this way, the tree node and its child nodes are added to the QTreewidget component object treeWidget. Each time it is opened, it will be added at the end of the tree node.

One thing to note here: The addresses pointed to by the QTreewidgetItem pointer objects here are all allocated on the heap. Will it cause a memory leak? Because of course the pointer as a local variable disappears after the function ends, but the memory address that saves the QTreeWidgetItem node is still there. Is there a way to release its memory address when needed? The answer is yes, and the node will be deleted later. Discussion.

4. Double-click a band to display the band image

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();

What is posted here is the method of finding the image path and sub-node band. As for displaying the image, it displays the band response grayscale image based on the image path and band number. This issue is not discussed and will be omitted.

5. Delete node

Deleting a node here does not delete all nodes, but deletes all nodes in the image related to the node. For example, if the mouse points to any child node of the second parent node in the original diagram, the parent node and all Child node is deleted.

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;
    }

The main method is to obtain the index number of the image in the top node based on the image path name, and then delete the top node and its sub-nodes. The takeTopLevelItem(index) method can be used to remove the node with index in the treeWidget. Note that this is just the When a node is removed from the treeWidget, its node (parent node + child node) still exists in the memory, so the address in the memory must also be released, otherwise there will be a so-called memory leak problem. The method adopted is to use the QTreeWidgetItem pointer to find the memory address where the node is stored, and then delete it. This will free up the memory space (if you have any questions, you can track and debug it). Be sure to delete all the nodes to be deleted and release them first. Child node memory, and then release the parent node memory.

It should also be noted that every time the memory space of a child node is cleared, the corresponding parent node will lose the child node. Therefore, the child node with the parent node index 0 is cleared every time, that is, the child of child(0) is obtained. node. In addition, don’t forget to remove the corresponding index content in the vector imgFile that saves the image path.

Summarize

What is given above is the core implementation part of the function, not a complete program. Others not discussed are irrelevant to the QTreeWidget control. The above method is highly portable and can be used where there are similar needs.

As a benefit for this article, you can receive a Qt development learning package and technical videos for free , including (Qt practical projects, C++ language basics, C++ design patterns, introduction to Qt programming, QT signal and slot mechanism, QT interface development-image drawing, QT network, QT database programming, QT project practice, QSS, OpenCV, Quick module, interview questions, etc.) ↓↓↓↓↓↓See below↓↓Click at the bottom of the article to receive the fee↓↓

Guess you like

Origin blog.csdn.net/m0_73443478/article/details/133168934