【Qt】QTableView添加下拉框过滤条件

实现通过带复选框的下拉框来为表格添加过滤条件
在这里插入图片描述

带复选框的下拉框

.h文件

#pragma once
#include <QCheckBox>
#include <QComboBox>
#include <QEvent>
#include <QLineEdit>
#include <QListWidget>

class TableComboBox : public QComboBox
{
    Q_OBJECT

public:
    TableComboBox(QWidget* parent = NULL);
    ~TableComboBox();

    // 隐藏下拉框
    virtual void hidePopup();

    // 添加一条选项
    void addItem(const QString& _text, const QVariant& _variant = QVariant());

    // 添加多条选项
    void addItems(const QStringList& _text_list);

    // 返回当前选中选项
    QStringList currentText();

    // 返回当前选项条数
    int count() const;

    // 设置搜索框默认文字
    void SetSearchBarPlaceHolderText(const QString _text);

    // 设置文本框默认文字
    void SetPlaceHolderText(const QString& _text);

    // 下拉框状态恢复默认
    void ResetSelection();

    // 清空所有内容
    void clear();

    // 文本框内容清空
    void TextClear();

    // 设置选中文本--单
    void setCurrentText(const QString& _text);

    // 设置选中文本--多
    void setCurrentText(const QStringList& _text_list);

    // 设置搜索框是否禁用
    void SetSearchBarHidden(bool _flag);

protected:
    // 事件过滤器
    virtual bool eventFilter(QObject* watched, QEvent* event);

    // 滚轮事件
    virtual void wheelEvent(QWheelEvent* event);

    // 按键事件
    virtual void keyPressEvent(QKeyEvent* event);

private slots:

    // 文本框文本变化
    void stateChange(int _row);

    // 点击下拉框选项
    void itemClicked(int _index);

signals:

    // 发送当前选中选项
    void selectionChange(const QString _data);

private:
    // 下拉框
    QListWidget* pListWidget;
    // 文本框,搜索框
    QLineEdit *pLineEdit, *pSearchBarEdit;
    // 搜索框显示标志
    bool isHidden;
    // 下拉框显示标志
    bool isShow;
};

.cpp文件

#include "PowerTableComboBox.h"

#include <QMessageBox>

#define FREEPTR(p) \
    if (p != NULL) \
    {              \
        delete p;  \
        p = NULL;  \
    }

TableComboBox::TableComboBox(QWidget* parent)
    : QComboBox(parent)
    , isHidden(true)
    , isShow(false)
{
    pListWidget = new QListWidget();
    pLineEdit = new QLineEdit();
    pSearchBarEdit = new QLineEdit();

    QListWidgetItem* currentItem = new QListWidgetItem(pListWidget);
    pSearchBarEdit->setPlaceholderText("搜索...");
    pSearchBarEdit->setClearButtonEnabled(true);
    pListWidget->addItem(currentItem);
    pListWidget->setItemWidget(currentItem, pSearchBarEdit);

    pLineEdit->setReadOnly(true);
    pLineEdit->installEventFilter(this);
    pLineEdit->setStyleSheet("QLineEdit:disabled{background:rgb(233,233,233);}");

    this->setModel(pListWidget->model());
    this->setView(pListWidget);
    this->setLineEdit(pLineEdit);
    connect(this, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &TableComboBox::itemClicked);
}

TableComboBox::~TableComboBox()
{
    FREEPTR(pLineEdit);
    FREEPTR(pSearchBarEdit);
}

void TableComboBox::hidePopup()
{
    isShow = false;
    int width = this->width();
    int height = this->height();
    int x = QCursor::pos().x() - mapToGlobal(geometry().topLeft()).x() + geometry().x();
    int y = QCursor::pos().y() - mapToGlobal(geometry().topLeft()).y() + geometry().y();
    if (x >= 0 && x <= width && y >= this->height() && y <= height + this->height())
    {
    }
    else
    {
        QComboBox::hidePopup();
    }
}

void TableComboBox::addItem(const QString& _text, const QVariant& _variant)
{
    Q_UNUSED(_variant);
    QListWidgetItem* item = new QListWidgetItem(pListWidget);
    QCheckBox* checkbox = new QCheckBox(this);
    checkbox->setText(_text);
    pListWidget->setItemWidget(item, checkbox);
    pListWidget->addItem(item);
    connect(checkbox, &QCheckBox::stateChanged, this, &TableComboBox::stateChange);
    checkbox->setChecked(true);
}

void TableComboBox::addItems(const QStringList& _text_list)
{
    for (const auto& text_one : _text_list)
    {
        addItem(text_one);
    }
}

QStringList TableComboBox::currentText()
{
    QStringList text_list;
    if (!pLineEdit->text().isEmpty())
    {
        // 以空格为分隔符分割字符串
        text_list = pLineEdit->text().split(' ');
    }
    return text_list;
}

int TableComboBox::count() const
{
    int count = pListWidget->count() - 1;
    if (count < 0)
    {
        count = 0;
    }
    return count;
}

void TableComboBox::SetSearchBarPlaceHolderText(const QString _text)
{
    pSearchBarEdit->setPlaceholderText(_text);
}

void TableComboBox::SetPlaceHolderText(const QString& _text)
{
    pLineEdit->setPlaceholderText(_text);
}

void TableComboBox::ResetSelection()
{
    int count = pListWidget->count();
    for (int i = 1; i < count; i++)
    {
        QWidget* widget = pListWidget->itemWidget(pListWidget->item(i));
        QCheckBox* check_box = static_cast<QCheckBox*>(widget);
        check_box->setChecked(false);
    }
}

void TableComboBox::clear()
{
    pLineEdit->clear();
    pListWidget->clear();
    QListWidgetItem* currentItem = new QListWidgetItem(pListWidget);
    pSearchBarEdit->setPlaceholderText("搜索...");
    pSearchBarEdit->setClearButtonEnabled(true);
    pListWidget->addItem(currentItem);
    pListWidget->setItemWidget(currentItem, pSearchBarEdit);
    SetSearchBarHidden(isHidden);
}

void TableComboBox::TextClear()
{
    pLineEdit->clear();
    ResetSelection();
}

void TableComboBox::setCurrentText(const QString& _text)
{
    int count = pListWidget->count();
    for (int i = 1; i < count; i++)
    {
        QWidget* widget = pListWidget->itemWidget(pListWidget->item(i));
        QCheckBox* check_box = static_cast<QCheckBox*>(widget);
        if (_text.compare(check_box->text()))
            check_box->setChecked(true);
    }
}

void TableComboBox::setCurrentText(const QStringList& _text_list)
{
    int count = pListWidget->count();
    for (int i = 1; i < count; i++)
    {
        QWidget* widget = pListWidget->itemWidget(pListWidget->item(i));
        QCheckBox* check_box = static_cast<QCheckBox*>(widget);
        if (_text_list.contains(check_box->text()))
            check_box->setChecked(true);
    }
}

void TableComboBox::SetSearchBarHidden(bool _flag)
{
    isHidden = _flag;
    pListWidget->item(0)->setHidden(isHidden);
}

bool TableComboBox::eventFilter(QObject* watched, QEvent* event)
{
    if (watched == pLineEdit && event->type() == QEvent::MouseButtonRelease && this->isEnabled())
    {
        showPopup();
        return true;
    }
    return false;
}

void TableComboBox::wheelEvent(QWheelEvent* event)
{
    Q_UNUSED(event);
}

void TableComboBox::keyPressEvent(QKeyEvent* event)
{
    QComboBox::keyPressEvent(event);
}

void TableComboBox::stateChange(int _row)
{
    Q_UNUSED(_row);
    QString selected_data("");
    int count = pListWidget->count();
    for (int i = 1; i < count; i++)
    {
        QWidget* widget = pListWidget->itemWidget(pListWidget->item(i));
        QCheckBox* check_box = static_cast<QCheckBox*>(widget);
        if (check_box->isChecked())
        {
        	// 添加空格做为分割符
            selected_data.append(check_box->text()).append(" ");
        }
    }
    selected_data.chop(1);
    if (!selected_data.isEmpty())
    {
        pLineEdit->setText(selected_data);
    }
    else
    {
        pLineEdit->clear();
    }

    // 文字从最左边开始显示
    pLineEdit->setToolTip(selected_data);
    pLineEdit->setSelection(0, 0);
    pLineEdit->setCursorPosition(0);

    emit selectionChange(selected_data);
}

void TableComboBox::itemClicked(int _index)
{
    if (_index != 0)
    {
        QCheckBox* check_box = static_cast<QCheckBox*>(pListWidget->itemWidget(pListWidget->item(_index)));
        check_box->setChecked(!check_box->isChecked());
    }
}

表格过滤器代理类

class TableProxyModel : public QSortFilterProxyModel
{
public:
    TableProxyModel (QObject* parent = nullptr)
        : QSortFilterProxyModel(parent)
    {}

protected:
    bool filterAcceptsRow(int source_row, const QModelIndex& source_parent) const override
    {
        QModelIndex targetTypeIndex = sourceModel()->index(source_row, 0, source_parent);
        QModelIndex boomNameIndex = sourceModel()->index(source_row, 1, source_parent);
        QModelIndex destructionDegreeIndex = sourceModel()->index(source_row, 2, source_parent);
        QString typeText = sourceModel()->data(targetTypeIndex).toString();
        QString nameText = sourceModel()->data(boomNameIndex).toString();
        int levelText = sourceModel()->data(destructionDegreeIndex).toInt();

        if (!isFilter)
        {
            return true;
        }

        bool matchType = false;
        bool matchName = false;
        bool levelText = false;
        for (QString type : sType)
        {
            if (typeText == type)
            {
                matchType = true;
                break;
            }
        }

        for (QString name : sName)
        {
            if (nameText == name)
            {
                matchName = true;
                break;
            }
        }

        for (int level: nLevelVec)
        {
            if (levelText == level)
            {
                matchLevel = true;
                break;
            }
        }

        if (matchLevel && matchName && matchType)
        {
            return true;
        }

        return false;
    }

public:
    QStringList sType;
    QStringList sName;
    QVector<int> nLevelVec;
    bool isFilter = false;
};

表格设置代理关联下拉框内容变更

添加代理

    tableView = new QTableView;
    proxyModel = new TableProxyModel;

    // 设置过滤规则来执行过滤
    proxyModel->setFilterRole(Qt::DisplayRole);
    proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
    proxyModel->setSourceModel(model);
    tableView->setModel(proxyModel);

下拉框关联表格代理

  1. 通过信号与槽关联
 connect(typeBox, &TableComboBox::selectionChange, this, &ShowTableView::filterBtnClick);
  1. 获取下拉框内容传到代理类做过滤
void ShowTableView::filterBtnClick(QString)
{
    // 复位
    proxyModel->isFilter = true;
    proxyModel->sType.clear();
    proxyModel->sName.clear();
    proxyModel->nLevelVec.clear();

    // 获取筛选条件
    proxyModel->sType = typeBox->currentText();
    proxyModel->sName= boomNameBox->currentText();
    for (QString level: levelBox->currentText())
    {
        proxyModel->nLevelVec.push_back(level.toInt());
    }
    proxyModel->setFilterFixedString("");
}
  1. 取消过滤,复位
void ShowTableView::noFilterBtnClick()
{
    proxyModel->isFilter = false;
    proxyModel->setFilterFixedString("");
}

截图

  1. 过滤前
  2. 过滤后
    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/905430.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java Executor ScheduledExecutorService 源码

前言 相关系列 《Java & Executor & 目录》《Java & Executor & ScheduledExecutorService & 源码》《Java & Executor & ScheduledExecutorService & 总结》《Java & Executor & ScheduledExecutorService & 问题》 涉及内容 …

C++:继承~派生类以及衍生的多继承与菱形继承问题

C中的继承其实是一个C中的坑,主要体现在其多继承(菱形继承)方面,我们先来了解下继承的概念 一,继承的概念与定义 1.1继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许我们在保持原有类特性的基础上进行扩展&#xff0c;增…

Python 从入门到实战43(Pandas数据结构)

我们的目标是&#xff1a;通过这一套资料学习下来&#xff0c;可以熟练掌握python基础&#xff0c;然后结合经典实例、实践相结合&#xff0c;使我们完全掌握python&#xff0c;并做到独立完成项目开发的能力。 上篇文章我们学习了NumPy数组操作的相关基础知识。今天学习一下pa…

工程项目智能化管理平台,SpringBoot框架智慧工地源码,实现工程建设施工可视化、智能化的全过程闭环管理。

智慧工地管理系统的建设以“1个可扩展性平台2个应用端3方数据融合N个智能设备”为原则。以“智、保、安、全”为导向&#xff0c;与工程建设管理信息系统、综合安防平台深度集成&#xff0c;构建统一的标准化工地平台&#xff0c;实现现场人员、车辆、项目、安全、进度等方面的…

使用React构建现代Web应用

&#x1f496; 博客主页&#xff1a;瑕疵的CSDN主页 &#x1f4bb; Gitee主页&#xff1a;瑕疵的gitee主页 &#x1f680; 文章专栏&#xff1a;《热点资讯》 使用React构建现代Web应用 1 引言 2 React简介 3 安装React 4 创建React项目 5 设计应用结构 6 创建组件 7 使用组件…

哈希——哈希表处理哈希冲突的方法

处理哈希冲突 实践中哈希表⼀般还是选择除法散列法作为哈希函数。 当然哈希表无论选择什么哈希函数也避免不了冲突&#xff08;主要作用就是减少冲突&#xff09;&#xff0c;那么插入数据时&#xff0c;如何解决冲突呢&#xff1f;主要有两种两种方法&#xff0c;开放定址法和…

海外云手机是什么?对外贸电商有什么帮助?

在外贸电商领域&#xff0c;流量引流已成为卖家们关注的核心问题。越来越多的卖家开始利用海外云手机&#xff0c;通过TikTok等社交平台吸引流量&#xff0c;以推动商品在海外市场的销售。那么&#xff0c;海外云手机到底是什么&#xff1f;它又能为外贸电商卖家提供哪些支持呢…

Hadoop-001-本地虚拟机环境搭建

一、安装VMware 官方下载VMware&#xff1a; https://vmware.mdsoft.top/?bd_vid5754305114651491003 二、下载镜像文件 阿里云镜像仓库&#xff1a; https://mirrors.aliyun.com/centos/ 本文档使用 CentOS-7-x86_64-DVD-1810-7.6.iso 搭建虚拟机 三、搭建虚拟机 1、编辑…

Oracle视频基础1.1.2练习

1.1.2 需求&#xff1a; 查询oracle组件和粒度大小&#xff0c; select component,granule_size from v$sga_dynamic_components;Oracle SGA 中组件和粒度大小查询详解 在 Oracle 数据库的内存结构中&#xff0c;SGA&#xff08;System Global Area&#xff0c;系统全局区&am…

动态上下文信念(DCB)

DCB&#xff08;动态上下文信念&#xff09;是一个用于累积通过注视获得信息的状态表示组件。它由三个部分组成&#xff1a; Fovea&#xff08;中央凹&#xff09;&#xff1a;接收来自注视位置周围区域的高分辨率视觉输入。Contextual beliefs&#xff08;上下文信念&#xf…

双月生日会:温暖相聚,共庆美好时刻

亲爱的华清远见西安中心的家人们&#xff1a; &#x1f389;&#x1f382; 在这金风送爽的秋日里&#xff0c;我们迎来了9、10月的生日会。在这个特别的日子里&#xff0c;我们聚集一堂&#xff0c;共同庆祝那些在这两个月份里出生的小伙伴们的生日。&#x1f382; 活动现场布…

Junit + Mockito保姆级集成测试实践

一、做好单测&#xff0c;慢即是快 对于单元测试的看法&#xff0c;业界同仁理解多有不同&#xff0c;尤其是在业务变化快速的互联网行业&#xff0c;通常的问题主要有&#xff0c;必须要做吗&#xff1f;做到多少合适&#xff1f;现在没做不也挺好的吗&#xff1f;甚至一些大…

【经典论文阅读11】ESMM模型——基于贝叶斯公式的CVR预估

传统的CVR模型&#xff08;也就是直接对conversion rate建模的模型&#xff09;在实际应用中面临两个问题&#xff08;样本选择偏差与数据稀疏性问题&#xff09;。为了解决这两个问题&#xff0c;本文提出ESMM模型。该模型巧妙地利用用户行为序列去建模这个问题&#xff0c;从…

使用Git进行版本控制的最佳实践

文章目录 Git简介基本概念仓库&#xff08;Repository&#xff09;提交&#xff08;Commit&#xff09;分支&#xff08;Branching&#xff09; 常用命令初始化仓库添加文件提交修改查看状态克隆仓库分支操作合并分支推送更改 最佳实践使用有意义的提交信息定期推送至远程仓库使…

Vision-Language Models for Vision Tasks: A Survey阅读笔记

虽然LLM的文章还没都看完&#xff0c;但是终究是开始看起来了VLM&#xff0c;首当其冲&#xff0c;当然是做一片文献综述啦。这篇文章比较早了&#xff0c;2024年2月份出的last version。 文章链接&#xff1a;https://arxiv.org/abs/2304.00685 GitHub链接&#xff1a;GitHu…

Oracle OCP认证考试考点详解082系列07

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 31. 第31题&#xff1a; 题目 解析及答案&#xff1a; 关于 “SET VERIFY ON” 命令&#xff0c;以下哪两个陈述是正确的&#xff1f; A…

网络搜索引擎Shodan(7)完结

声明&#xff1a;学习视频来自b站up主 泷羽sec&#xff0c;如涉及侵权马上删除文章 声明&#xff1a;本文主要用作技术分享&#xff0c;所有内容仅供参考。任何使用或依赖于本文信息所造成的法律后果均与本人无关。请读者自行判断风险&#xff0c;并遵循相关法律法规。 感谢泷…

【C++ 算法进阶】算法提升八

复杂计算 &#xff08;括号问题相关递归套路 重要&#xff09; 题目 给定一个字符串str str表示一个公式 公式里面可能有整数 - * / 符号以及左右括号 返回最终计算的结果 题目分析 本题的难点主要在于可能会有很多的括号 而我们直接模拟现实中的算法的话code会难写 要考虑…

​IOT NTN 与 NR NTN​

NTN&#xff08;Non-Terrestrial Network)&#xff09;&#xff0c;即非地面网络通信&#xff0c;通过不同轨道高度的卫星对地面上的终端提供网络连接的服务。利用卫星通信网络与地面蜂窝网络的融合&#xff0c;可以在不受地形地貌的限制和影响下&#xff0c;连通空、天、地、海…

44-RK3588s调试 camera-engine-rkaiq(rkaiq_3A_server)

在RK3588s平台上调试imx415 camera sensor 过程中&#xff0c;已经识别到了camera sensor ID&#xff0c;并且可以拿到raw图和isp处理后的图像&#xff0c;但是isp处理后的图像偏绿&#xff0c;来看查看后台服务发现rkaiq_3A_server没有运行&#xff0c;然后单独运行rkaiq_3A_s…