QT QTreeWidget 实现模糊查询和多选的勾选状态

简介: #QT QTreeWidget 实现模糊查询和勾选状态本文的主要代码基本都是总结2篇博客实现了模糊查询模糊查询和勾选状态QTreeWidget实现勾选基本上所有的操作都是递归操作,个人测试了性能,如果1w项左右的数据时,没啥问题,如果有几w,那么勾选所有的,效率很慢,需要几秒钟,大家可以测试,不废话了,直接上代码:如果有啥不懂的,可以在留言,会很详细的给出解释的

#QT QTreeWidget 实现模糊查询和勾选状态

本文的主要代码基本都是总结2篇博客实现了模糊查询模糊查询和勾选状态QTreeWidget实现勾选基本上所有的操作都是递归操作,个人测试了性能,如果1w项左右的数据时,没啥问题,如果有几w,那么勾选所有的,效率很慢,需要几秒钟,大家可以测试,不废话了,直接上代码:如果有啥不懂的,可以在留言,会很详细的给出解释的

以下是头文件

#ifndef CTREEWEIGHTWITHSEARCH_H
#define CTREEWEIGHTWITHSEARCH_H
#pragma execution_character_set("utf-8") //解决中文乱码
#include <QLineEdit>
#include <QTreeWidget>
#include <QGridLayout>
#include <QWidget>
#include <QPointer>
/**
 * @brief The CTreeWeightWithSearch class 带有搜索的节点树
 * 1.可选是否需要搜索框
 * 2.单选或者多选参数设置
 */
class CTreeWeightWithSearch : public QWidget
{
    Q_OBJECT
public:
    explicit CTreeWeightWithSearch(QWidget *parent = nullptr,bool bShowSearchEdit=true,bool bCanMultiSelect=true,bool bShowCheckBox=true,bool bCheckedParentNeedCheckChildren=true);
    ~CTreeWeightWithSearch();
    //测试数据,在使用时,在其他地方调用AddTreeRoot和AddTreeNode即可
    void initData();
    QTreeWidgetItem * AddTreeRoot(const QStringList &strColumnList,QIcon icon =QIcon(""),int nIconColumn = 0);
    QTreeWidgetItem * AddTreeNode(QTreeWidgetItem *parent,const QStringList &strColumnList,QIcon icon =QIcon(""),int nIconColumn = 0);//添加孩子节点
    QList<QTreeWidgetItem *> getCheckedItems();//得到所有item的checked状态
    //获取item孩子的勾选状态
    void getItemChildOfCheckedState(QTreeWidgetItem *item);
    //根据模糊文字显示项(如果和模糊文字匹配的话)
    void hideOrShowItemBySearchText(const QString &strBlurrySearchText);
    void hideOrShowChildItemsBySearchText(QTreeWidgetItem *item,const QString &strBlurrySearchText);//显示或者隐藏孩子项
    //显示父亲项(主要是模糊查询时,如果孩子被查询到,父亲没有被查询到,需要显示父亲)
    void updateShowParentItem(QTreeWidgetItem *item);
    bool &showSearchEdit(){return m_bShowSearchEdit;}
    bool &canMultiSelect(){return m_bCanMultiSelect;}
    bool &showCheckBox(){return m_bShowCheckBox;}
    bool &checkedParentNeedCheckChildren(){return m_bCheckedParentNeedCheckChildren;}
private:
    void init();
    void updateParentItem(QTreeWidgetItem* item);//更新父级项的选择状态
    void setItemCheckState(QTreeWidgetItem* item);//设置选择项的状态
    static const constexpr QSize m_sizeInitial =QSize(300,600);//初始化大小
    //控件对象
    QPointer<QLineEdit> m_pSearchLineEdit;//搜索控件
    QPointer<QTreeWidget> m_pTreeWeight;//树控件
    QPointer<QGridLayout> m_pGridLayout;//布局
    //控制变量
    QList<QTreeWidgetItem *> m_pListCheckedItems;//存放所有勾选状态的项
    bool m_bShowSearchEdit;//是否显示搜索编辑框
    bool m_bCanMultiSelect;//是否可以多选
    bool m_bShowCheckBox;//是否显示复选框
    bool m_bCheckedParentNeedCheckChildren;//父亲勾选时是否需要勾选孩子节点
signals:
public slots:
   void on_treeItemCheckChange(QTreeWidgetItem* item,int column);//处理勾选的槽函数
   void on_textChanged(const QString &);//处理搜索框变化的槽函数
};
#endif // CTREEWEIGHTWITHSEARCH_H

以下是CPP文件

#include <QDebug>
#include "ctreeweightwithsearch.h"
CTreeWeightWithSearch::CTreeWeightWithSearch(QWidget *parent,bool bShowSearchEdit,bool bCanMultiSelect,
                                             bool bShowCheckBox,bool bCheckedParentNeedCheckChildren)
    : QWidget(parent),
    m_pSearchLineEdit(new QLineEdit()),
    m_pTreeWeight(new QTreeWidget()),
    m_pGridLayout(new QGridLayout()),
    m_bShowSearchEdit(bShowSearchEdit),
    m_bCanMultiSelect(bCanMultiSelect),
    m_bShowCheckBox(bShowCheckBox),
    m_bCheckedParentNeedCheckChildren(bCheckedParentNeedCheckChildren)
{
    setAttribute(Qt::WA_DeleteOnClose);
    init();
    initData();
}
CTreeWeightWithSearch::~CTreeWeightWithSearch()
{
    if(m_pSearchLineEdit)
    {
        delete m_pSearchLineEdit;
        m_pSearchLineEdit = nullptr;
    }
    if(m_pTreeWeight)
    {
        delete  m_pTreeWeight;
        m_pTreeWeight = nullptr;
    }
    if(m_pGridLayout)
    {
        delete m_pGridLayout;
        m_pGridLayout = nullptr;
    }
}
void CTreeWeightWithSearch::initData()//测试数据
{
    QTreeWidgetItem * beiJingItem = AddTreeRoot(QStringList() <<tr("北京"),QIcon(":/images/icon.png"));//想要显示图标,直接找一个对应的图标即可显示
    for(int i = 0 ; i < 200; ++i)
    {
        QTreeWidgetItem *pTem = AddTreeNode(beiJingItem,QStringList() <<tr("朝阳"));
        QTreeWidgetItem *aTem = AddTreeNode(pTem,QStringList() <<tr("四合村"));
        AddTreeNode(aTem,QStringList() <<tr("四合小村"));
        QTreeWidgetItem *cItem = AddTreeNode(beiJingItem,QStringList() <<tr("海淀"));
        QTreeWidgetItem * HeiBeiItem = AddTreeNode(cItem,QStringList() <<tr("河北"));
        AddTreeNode(HeiBeiItem,QStringList() <<tr("石家庄"));
    }
}
/**
 * @brief CTreeWeightWithSearch::AddTreeRoot :添加根节点,可以是多个根节点,也可以只有一个根节点,看自己的需求是怎么样的
 * @param strColumnList:数据列参数
 * @param icon :设置图标
 * @param nIconColumn :图标列(默认一般是第一列,尝试为0)
 * @return
 */
QTreeWidgetItem *CTreeWeightWithSearch::AddTreeRoot(const QStringList &strColumnList,QIcon icon, int nIconColumn)
{
    QTreeWidgetItem * item=new QTreeWidgetItem(strColumnList);
    if(m_bShowCheckBox)
    {
        item->setCheckState(0,Qt::Unchecked);//
    }
    item->setIcon(nIconColumn,icon);
    m_pTreeWeight->addTopLevelItem(item);//作为顶级节点
    return item;
}
/**
 * @brief CTreeWeightWithSearch::AddTreeNode 添加孩子节点
 * @param parent
 * @param strColumnList
 * @return
 */
QTreeWidgetItem *CTreeWeightWithSearch::AddTreeNode(QTreeWidgetItem *parent, const QStringList &strColumnList,QIcon icon, int nIconColumn)
{
    QTreeWidgetItem * item=new QTreeWidgetItem(strColumnList);
    if(m_bShowCheckBox)
    {
        item->setCheckState(0,Qt::Unchecked);
    }
    item->setIcon(nIconColumn,icon);
    parent->addChild(item);
    return item;
}
//获取所有选择的项
QList<QTreeWidgetItem *> CTreeWeightWithSearch::getCheckedItems()
{
    m_pListCheckedItems.clear();
    for(int i = 0; i < m_pTreeWeight->topLevelItemCount(); ++i)
    {
        QTreeWidgetItem *pParentItem(m_pTreeWeight->topLevelItem(i));
        //如果父亲节点已选择,则孩子节点都是勾选状态
        if(pParentItem->checkState(0) == Qt::Checked)//勾选了
        {
            m_pListCheckedItems.push_back(pParentItem);
        }
        getItemChildOfCheckedState(pParentItem);//处理孩子节点的勾选状态
    }
    return m_pListCheckedItems;
}
/**
 * @brief CTreeWeightWithSearch::getItemChildOfCheckedState 判断项的孩子是否勾选
 * @param item
 */
void CTreeWeightWithSearch::getItemChildOfCheckedState(QTreeWidgetItem *item)
{
    for(int i = 0; i < item->childCount(); ++i)
    {
        QTreeWidgetItem *childItem(item->child(i));
        if(childItem->checkState(0) == Qt::Checked)
        {
            m_pListCheckedItems.push_back(childItem);
        }
        getItemChildOfCheckedState(childItem);//递归处理孩子节点的孩子
    }
}
/**
 * @brief CTreeWeightWithSearch::hideOrShowItemBySearchText : 根据查询文字显示项
 * @param strBlurrySearchText 查询文字
 */
void CTreeWeightWithSearch::hideOrShowItemBySearchText(const QString &strBlurrySearchText)
{
    for(int i = 0; i < m_pTreeWeight->topLevelItemCount(); ++i)
    {
        QTreeWidgetItem *pParentItem(m_pTreeWeight->topLevelItem(i));
        if(pParentItem->text(0).contains(strBlurrySearchText,Qt::CaseInsensitive))//如果项目的第一列文字包含查询的文字
        {
            if(pParentItem->isHidden())
                pParentItem->setHidden(false);
        }
        else
        {
            pParentItem->setHidden(true);
        }
        hideOrShowChildItemsBySearchText(pParentItem,strBlurrySearchText);//处理孩子节点的勾选状态
    }
}
void CTreeWeightWithSearch::hideOrShowChildItemsBySearchText(QTreeWidgetItem *item, const QString &strBlurrySearchText)
{
    for(int i = 0; i < item->childCount(); ++i)
    {
        QTreeWidgetItem *childItem(item->child(i));
        if(!childItem->text(0).contains(strBlurrySearchText,Qt::CaseInsensitive))//孩子没有匹配,隐藏孩子
        {
            childItem->setHidden(true);
        }
        else
        {
            childItem->setHidden(false);
            updateShowParentItem(childItem);//显示父亲的状态
        }
        hideOrShowChildItemsBySearchText(childItem,strBlurrySearchText);//处理孩子节点的勾选状态
    }
    if(strBlurrySearchText == "")//如果没有输入文字,只显示最外一层,主要是数据多了,数据项过长
    {
        if(item->isExpanded())
        {
            item->setExpanded(false);
        }
    }
}
//如果孩子显示,就递归让父亲显示
void CTreeWeightWithSearch::updateShowParentItem(QTreeWidgetItem *item)
{
    QTreeWidgetItem *parent(item->parent());
    if(!parent)
        return;
    parent->setHidden(false);
    if(!parent->isExpanded())
    {
        parent->setExpanded(true);
    }
    updateShowParentItem(parent);//递归显示父亲
}
void CTreeWeightWithSearch::init()
{
    resize(m_sizeInitial);
    //布局
    if(m_bShowSearchEdit)
    {
        m_pGridLayout->addWidget(m_pSearchLineEdit,0,0,1,1);
    }
    m_pGridLayout->addWidget(m_pTreeWeight,1,0,1,1);
    m_pGridLayout->setContentsMargins(2,5,2,2);
    m_pGridLayout->setVerticalSpacing(10);
    setLayout(m_pGridLayout);
    //设置样式表
    m_pSearchLineEdit->setPlaceholderText(tr("请输入"));
    m_pSearchLineEdit->setStyleSheet("border:1px groove #DCDFE6;border-radius:3px;padding:2px 4px;color:#606266;");
    m_pTreeWeight->setHeaderHidden(true);//
    if(m_bShowCheckBox || (!m_bShowCheckBox && m_bCanMultiSelect))//可以多选
    {
        m_pTreeWeight->setSelectionMode(QAbstractItemView::MultiSelection);//多选
    }
    else
    {
        m_pTreeWeight->setSelectionMode(QAbstractItemView::SingleSelection);//单选
    }
    m_pTreeWeight->setIconSize(QSize(14,14));//设置图标大小
    m_pTreeWeight->setEditTriggers(QAbstractItemView::NoEditTriggers);//
    m_pTreeWeight->setFocusPolicy(Qt::NoFocus);//去除选择时的虚线框
    //初始化槽函数
    connect(m_pTreeWeight,SIGNAL(itemClicked( QTreeWidgetItem*,int)),this,
            SLOT(on_treeItemCheckChange( QTreeWidgetItem *,int)));//项点击事件
    connect(m_pSearchLineEdit,SIGNAL(textChanged(const QString &)),this,
            SLOT(on_textChanged(const QString &)));
}
void CTreeWeightWithSearch::updateParentItem(QTreeWidgetItem *item)
{
    QTreeWidgetItem *parent = item->parent();
    if (!parent)
        return;
    int nSelectedCount = 0;
    int childCount = parent->childCount();
    for (int i = 0; i < childCount; i++) //判断有多少个子项被选中
    {
        QTreeWidgetItem* childItem = parent->child(i);
        if (childItem->checkState(0) == Qt::Checked || 
        childItem->checkState(0) == Qt::PartiallyChecked)
        {
            nSelectedCount++;
        }
    }
    if (nSelectedCount <= 0)  //如果没有子项被选中,父项设置为未选中状态
        parent->setCheckState(0, Qt::Unchecked);
    else if (nSelectedCount > 0 && nSelectedCount < childCount)    //如果有部分子项被选中,父项设置为部分选中状态,即用灰色显示
        parent->setCheckState(0, Qt::PartiallyChecked);
    else if (nSelectedCount == childCount)    //如果子项全部被选中,父项则设置为选中状态
        parent->setCheckState(0, Qt::Checked);
    updateParentItem(parent);
}
void CTreeWeightWithSearch::setItemCheckState(QTreeWidgetItem *item)
{
    int count = item->childCount(); //返回子项的个数
    if (Qt::Checked == item->checkState(0))//勾选状态
    {
        if (count > 0)//孩子数大于0
        {
            for (int i = 0; i < count; i++)
            {
                item->child(i)->setCheckState(0, Qt::Checked);
                //处理孩子的勾选状态(有点啰嗦,不过实现了,如果节点有点多,如果选择最上层,可能需要几秒的时间)
                setItemCheckState(item->child(i));
            }
        }
        else
            updateParentItem(item);//更新父亲的状态
    }
    else if (Qt::Unchecked == item->checkState(0))
    {
        if (count > 0)//孩子数大于0
        {
            for (int i = 0; i < count; i++)
            {
                item->child(i)->setCheckState(0, Qt::Unchecked);
                setItemCheckState(item->child(i));//处理孩子的勾选状态
            }
        }
        else //更新父亲的状态
            updateParentItem(item);
    }
}
void CTreeWeightWithSearch::on_treeItemCheckChange(QTreeWidgetItem *item, int column)
{
    if(m_bShowCheckBox && m_bCheckedParentNeedCheckChildren) //需要处理孩子与父亲勾选状态时,才处理
    {
        if( column!=0)//不是0列,不处理
            return;
        setItemCheckState(item);
    }
}
void CTreeWeightWithSearch::on_textChanged(const QString &strText)
{
    hideOrShowItemBySearchText(strText);
}

使用方式

*CTreeWeightWithSearch pTreeWeight = new CTreeWeightWithSearch();

pTreeWeight->show();

结果截图:

8424c1201da9ff897543dcb340d9bf12_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2FiY2Q1NTIxOTE4Njg=,size_16,color_FFFFFF,t_70.png

181d35f73db7a9bbbd4f39295e492ef4_watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2FiY2Q1NTIxOTE4Njg=,size_16,color_FFFFFF,t_70.png



相关文章
|
6月前
|
数据库 开发者 Windows
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解-2
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解
|
6月前
|
XML 设计模式 JSON
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解-1
QT 项目视图(QListView&QTreeView&QTableView)和项目部件(QListWidget&QTreeWidget&QTableWidget)详解
|
6月前
|
索引 Windows
【qt】QTreeWidget 树形组件2
【qt】QTreeWidget 树形组件
53 0
|
6月前
|
C++
【qt】QTreeWidget 树形组件1
【qt】QTreeWidget 树形组件
61 0
案例分享:Qt九宫格图片资源浏览器(支持window、linux、兼容各国产系统,支持子文件夹,多选,全选,图片预览,行数与列数设置等)
案例分享:Qt九宫格图片资源浏览器(支持window、linux、兼容各国产系统,支持子文件夹,多选,全选,图片预览,行数与列数设置等)
案例分享:Qt九宫格图片资源浏览器(支持window、linux、兼容各国产系统,支持子文件夹,多选,全选,图片预览,行数与列数设置等)
|
存储 程序员 C#
Python Qt GUI设计:QTableView、QListView、QListWidet、QTableWidget、QTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)
Python Qt GUI设计:QTableView、QListView、QListWidet、QTableWidget、QTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)
Python Qt GUI设计:QTableView、QListView、QListWidet、QTableWidget、QTreeWidget和QTreeWidgetltem表格和树类(提升篇—1)
|
数据库 数据库连接 数据安全/隐私保护
3.QT数据库综合案例,模糊查询等操作
 1 新建一个项目: Database01.pro SOURCES += \     main.cpp \     Contact.cpp   QT += gui widgets sql   CONFIG += C++11   HEADERS +=
2245 0
|
4月前
|
数据安全/隐私保护 C++ 计算机视觉
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
180 1
Qt(C++)开发一款图片防盗用水印制作小工具
|
3月前
|
监控 C++ 容器
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
88 0