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

news2024/10/24 7:50:37

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

带复选框的下拉框

.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. 过滤后
    在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

前端构建工具vite的优势

1. 极速冷启动 Vite 使用原生 ES 模块 (ESM) 在开发环境下进行工作。相比于传统构建工具需要打包所有的文件&#xff0c;Vite 只在浏览器请求模块时动态加载所需的文件。无打包冷启动&#xff1a;无需预先打包&#xff0c;项目启动非常快&#xff0c;尤其对于大型项目效果更明…

顺序表(一)(数据结构)

一. 线性表 线性表&#xff08;linear list&#xff09;是n个具有相同特性的数据元素的有限序列 。 线性表是一种在实际中广泛使用的数据结构&#xff0c;常见的线性表&#xff1a;顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构&#xff0c;是人为想象出来的数…

HCIP--1

同一区域内的OSPF路由器拥有一致的 LSDB, 在区域内&#xff0c;OSPF 采用 SPF算法计算路由一个区域太多路由器&#xff0c;硬件资源跟不上&#xff0c;所以多划分区域 OSPF 路由计算原理 1. 区域内路由计算 LSA 在OSPF中&#xff0c;每个路由器生成 LSA&#xff0c;用于告诉…

【部署篇】RabbitMq-03集群模式部署

一、准备主机 准备3台主机用于rabbitmq部署&#xff0c;文章中是在centos7上安装部署rabbitmq3.8通过文章中介绍的方式可以同样在centos8、centos9上部署&#xff0c;只需下载对应的版本进行相同的操作。 主机IP角色说明192.168.128.31种子节点192.168.128.32普通节点192.16…

Matlab学习01-矩阵

目录 一&#xff0c;矩阵的创建 1&#xff0c;直接输入法创建矩阵 2&#xff0c;利用M文件创建矩阵 3&#xff0c;利用其它文本编辑器创建矩阵 二&#xff0c;矩阵的拼接 1&#xff0c;基本拼接 1&#xff09; 水平方向的拼接 2&#xff09;垂直方向的拼接 3&#xf…

Linux系统基础-进程间通信(5)_模拟实现命名管道和共享内存

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 Linux系统基础-进程间通信(5)_模拟实现命名管道和共享内存 收录于专栏[Linux学习] 本专栏旨在分享学习Linux的一点学习笔记&#xff0c;欢迎大家在评论区交流讨…

LeetCode--删除并获得点数--动态规划

一、题目解析 二、算法原理 根据题意&#xff0c;在选择了元素 x 后&#xff0c;该元素以及所有等于 x−1 或 x1 的元素会从数组中删去。若还有多个值为 x 的元素&#xff0c;由于所有等于 x−1 或 x1 的元素已经被删除&#xff0c;我们可以直接删除 x 并获得其点数。因此若选…

Win10+MinGW13.1.0编译Qt5.15.15

安装windows SDK、python、ruby、cmake、Perl[可选]安装MySQL解压qt-everywhere-opensource-src-5.15.15.zip&#xff08;注&#xff1a;不要使用qt-everywhere-opensource-src-5.15.15.tar.xz&#xff09;修改源代码 E:\qt-everywhere-src-5.15.15\qtbase\src\3rdparty\angle\…

hive数据库,表操作

1.创建; create database if not exists myhive; use myhive; 2.查看: 查看数据库详细信息:desc database myhive; 默认数据库的存放路径是 HDFS 的&#xff1a; /user/hive/warehouse 内 补充:创建数据库并指定 hdfs 存储位置:create database myhive2 location /myhive2 3.…

<项目代码>YOLOv8路面垃圾识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

Codeforces Round 881 (Div. 3)(A~F1题解)

这场比赛可能是因为比较老吧&#xff0c;我感觉很轻松&#xff0c;就是第五个卡了一下&#xff0c;看错题了&#xff0c;原本应该是严格大于的&#xff0c;从而导致代码一直出现bug&#xff0c;在1小时20分钟才解决 A. Sasha and Array Coloring 题意&#xff1a;就是说给你n个…

提权 | Windows系统

文章目录 cmd提权meterpreter提权getsystemsteal_tokenmigrate 令牌窃取(MS16-075)烂土豆提权步骤烂土豆提权原理 sc命令提权抓本地密码提权其他工具pr工具 内核提权WindowsVulScan cmd提权 前言&#xff1a;我们getshell一个用windows部署的网站后&#xff0c;通过蚁剑或者其…

ESP32 S3 语音识别 语音唤醒程序流程

ESP32 S3 语音识别 语音唤醒程序流程 参考例程首先进行esp_periph_set_init 初始化之后执行setup_player&#xff0c;之后执行start_recorder&#xff0c;识别的主处理voice_read_task 参考例程 D:\Espressif\esp-adf\examples\speech_recognition\wwe\ 首先进行esp_periph_se…

零知识学习WLAN漫游二、无线漫游介绍(2)

接前一篇文章&#xff1a;零知识学习WLAN漫游一、无线漫游介绍&#xff08;1&#xff09; 本文内容参考&#xff1a; WLAN漫游简介_漫游主动性-CSDN博客 无线漫游_百度百科 无线漫游简述-CSDN博客 特此致谢&#xff01; 一、WLAN漫游简介 3. 漫游协议和快速漫游协议 802.…

算法的学习笔记—数字在排序数组中出现的次数(牛客JZ53)

&#x1f600;前言 在编程中&#xff0c;查找有序数组中特定元素的出现次数是一个常见的问题。本文将详细讲解这个问题的解决方案&#xff0c;并通过二分查找法优化效率。 &#x1f3e0;个人主页&#xff1a;尘觉主页 文章目录 &#x1f970;数字在排序数组中出现的次数&#x…

九、pico+Unity交互开发——触碰抓取

一、VR交互的类型 Hover&#xff08;悬停&#xff09; 定义&#xff1a;发起交互的对象停留在可交互对象的交互区域。例如&#xff0c;当手触摸到物品表面&#xff08;可交互区域&#xff09;时&#xff0c;视为触发了Hover。 Grab&#xff08;抓取&#xff09; 概念&#xff…

深入浅出:深度学习模型部署全流程详解

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; Yaoyao2024往期回顾&#xff1a; 【论文精读】PSAD&#xff1a;小样本部件分割揭示工业异常检测的合成逻辑每日一言&#x1f33c;: 生活要有所期待&#xff0c; 否则就如同罩在…

【国潮来袭】华为原生鸿蒙 HarmonyOS NEXT(5.0)正式发布:鸿蒙诞生以来最大升级,碰一碰、小艺圈选重磅上线

在昨日晚间的原生鸿蒙之夜暨华为全场景新品发布会上&#xff0c;华为原生鸿蒙 HarmonyOS NEXT&#xff08;5.0&#xff09;正式发布。 华为官方透露&#xff0c;截至目前&#xff0c;鸿蒙操作系统在中国市场份额占据 Top2 的领先地位&#xff0c;拥有超过 1.1 亿 的代码行和 6…

想让前后端交互更轻松?alovajs了解一下?

作为一个前端开发者&#xff0c;我最近发现了一个超赞的请求库 alovajs&#xff0c;它真的让我眼前一亮&#xff01;说实话&#xff0c;我感觉自己找到了前端开发的新大陆。大家知道&#xff0c;在前端开发中&#xff0c;处理 Client-Server 交互一直是个老大难的问题&#xff…

查缺补漏----用户工作区,系统缓冲区,外设工作最短时间计算

对于下面这一题&#xff0c;分析起来很简单&#xff1a; 答案&#xff1a;C 以上是单缓冲区&#xff0c;补充双缓冲区是什么情况&#xff1a; 1.假设磁盘块与缓冲区大小相同&#xff0c;每个盘块读入缓冲区的时间为15us&#xff0c;由缓冲区送至用户区的时间是5us&#xff0c…