QTableWidget设置表头筛选(含鼠标点击事件过滤)

QtableWidget设置表头点击事件,显示筛选框,实现类似excel的表头筛选功能;
通过重写eventFilter事件过滤方法,获取鼠标点击的事件(含点击表格的空白处)

效果图


在这里插入图片描述

Widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTableWidget>
#include <QToolButton>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QEvent>

#include "FilterWidget.h"
class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

	//初始化
    void Init();

	//插入测试数据
	void InsertDatas();

	//筛选
	void filter(int col, QStringList showList);

	//关闭筛选框
	void closeFilterWidget();

	//事件过滤
	bool eventFilter(QObject *obj, QEvent *e);

	//初始化map
	void initMap();

private slots:
	//表头点击槽函数
    void onHeaderClicked(int);

private:
	QTableWidget *m_tableWidget = nullptr;

	//筛选框
	FilterWidget* m_filterWidget = nullptr;

	//列号,显示的元素
	QMap<int, QStringList> m_map;

};

#endif // WIDGET_H

Widget.cpp

#include "widget.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QRadioButton>
#include <QMessageBox>
#include <QSet>
#include <QMouseEvent>

#pragma execution_character_set("utf-8")

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    //初始化
    Init();

	//插入测试数据
	InsertDatas();

    QVBoxLayout* lay = new QVBoxLayout(this);
    lay->setMargin(0);
    lay->setSpacing(0);
    setLayout(lay);
    lay->addWidget(m_tableWidget);

	//注册事件过滤
	m_tableWidget->viewport()->installEventFilter(this);
}

Widget::~Widget()
{
	if (m_filterWidget != nullptr)
	{
		delete m_filterWidget;
		m_filterWidget = nullptr;
	}
}

//初始化表格
void Widget::Init()
{
    m_tableWidget = new QTableWidget(this);

    //表头字体居中
    m_tableWidget->horizontalHeader()->setDefaultAlignment(Qt::AlignHCenter);
    //自适应宽度
    m_tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
    //使行列头自适应宽度,最后一列将会填充空白部分
    m_tableWidget->horizontalHeader()->setStretchLastSection(true);
    //设置行选中
    m_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
    //选中多行,可以使用shift,ctrl
    //SingleSelection-单选
    //MultiSelection-多选
    //ExtendedSelection-支持shift,ctrl和Ctr+A操作
    m_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);
    //禁止编辑
    m_tableWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);

    //隐藏垂直表头
    //m_tableWidget->verticalHeader()->hide();

    m_tableWidget->setColumnWidth(0, 150);
    m_tableWidget->setColumnWidth(1, 80);
    m_tableWidget->setColumnWidth(2, 80);
    m_tableWidget->setColumnWidth(3, 250);
    m_tableWidget->setColumnWidth(4, 50);

    QStringList headerLabels;
    headerLabels << QString("列1") << QString("列2") << QString("列3") << QString("列4") << QString("列5");
    m_tableWidget->setColumnCount(headerLabels.size());
    m_tableWidget->setHorizontalHeaderLabels(headerLabels);

    //表头点击
    connect(m_tableWidget->horizontalHeader()
            , SIGNAL(sectionClicked(int))
            ,this
            , SLOT(onHeaderClicked(int)));
}

//插入测试数据
void Widget::InsertDatas()
{
	for (int i = 0; i < 2; i++)
	{
		int row = m_tableWidget->rowCount();
		m_tableWidget->insertRow(row);
		m_tableWidget->setItem(row, 0, new QTableWidgetItem(QString("1")));
		m_tableWidget->setItem(row, 1, new QTableWidgetItem(QString("1")));
		m_tableWidget->setItem(row, 2, new QTableWidgetItem(QString("1")));
		m_tableWidget->setItem(row, 3, new QTableWidgetItem(QString("1")));
		m_tableWidget->setItem(row, 4, new QTableWidgetItem(QString("1")));
	}

	for (int i = 0; i < 2; i++)
	{
		int row = m_tableWidget->rowCount();
		m_tableWidget->insertRow(row);
		m_tableWidget->setItem(row, 0, new QTableWidgetItem(QString("2")));
		m_tableWidget->setItem(row, 1, new QTableWidgetItem(QString("2")));
		m_tableWidget->setItem(row, 2, new QTableWidgetItem(QString("2")));
		m_tableWidget->setItem(row, 3, new QTableWidgetItem(QString("2")));
		m_tableWidget->setItem(row, 4, new QTableWidgetItem(QString("2")));
	}

	for (int i = 0; i < 2; i++)
	{
		int row = m_tableWidget->rowCount();
		m_tableWidget->insertRow(row);
		m_tableWidget->setItem(row, 0, new QTableWidgetItem(QString("1")));
		m_tableWidget->setItem(row, 1, new QTableWidgetItem(QString("3")));
		m_tableWidget->setItem(row, 2, new QTableWidgetItem(QString("3")));
		m_tableWidget->setItem(row, 3, new QTableWidgetItem(QString("3")));
		m_tableWidget->setItem(row, 4, new QTableWidgetItem(QString("2")));
	}

	//初始化map
	initMap();
}

//初始化map
void Widget::initMap()
{
	for (int col = 0; col < m_tableWidget->columnCount(); col++)
	{
		QStringList strList;
		for (int row = 0; row < m_tableWidget->rowCount(); row++)
		{
			QString	strItem = m_tableWidget->item(row, col)->text();
			strList.append(strItem);
		}
		m_map[col] = strList;
	}
}

//筛选
void Widget::filter(int col, QStringList showList)
{
	m_map[col] = showList;
	for (int i = 0; i < m_tableWidget->rowCount(); i++)
	{
		bool hidden = false;

		//遍历map
		for each (int  v_col in m_map.keys())
		{
			QString strItem = m_tableWidget->item(i, v_col)->text();
			if (!m_map.value(v_col).contains(strItem))
			{
				hidden = true;
				break;
			}
		}

		m_tableWidget->setRowHidden(i, hidden);
	}
}

//表头点击槽函数
void Widget::onHeaderClicked(int col)
{
	//所有item
	QSet<QString> items;
	//显示的item
	QSet<QString> showItems;
	//行数
	int rows = m_tableWidget->rowCount();
	//遍历列表
	for (int i = 0; i < rows; i++)
	{
		QString strItem = m_tableWidget->item(i, col)->text();
		items.insert(strItem);
		if (m_map.value(col).contains(strItem))
		{
			showItems.insert(strItem);
		}
	}
	//转为QStringList
	QStringList strItems;
	QStringList strShowItems;
	for each (QString var in items)
	{
		strItems.append(var);
	}

	for each (QString var in showItems)
	{
		strShowItems.append(var);
	}
	//关闭筛选框
	closeFilterWidget();
	//新建筛选框
	m_filterWidget = new FilterWidget(strItems, strShowItems, col, m_tableWidget);
	m_filterWidget->exec(m_tableWidget->mapFromGlobal(cursor().pos()));
}

//事件过滤
bool Widget::eventFilter(QObject *target, QEvent *event)
{
	QMouseEvent *e = static_cast<QMouseEvent *>(event);

	if (e == nullptr)
	{
		return QWidget::eventFilter(target, event);
	}

	if (e->type() == QEvent::MouseButtonPress || e->type() == QEvent::MouseButtonRelease)
	{
		closeFilterWidget();

	}

	return QWidget::eventFilter(target, event);
}

//关闭筛选框
void Widget::closeFilterWidget()
{
	//清空筛选框
	if (m_filterWidget != nullptr)
	{
		QStringList showList = m_filterWidget->getShowList();
		filter(m_filterWidget->getColumn(), showList);

		delete m_filterWidget;
		m_filterWidget = nullptr;
	}
}


FilterWidget.h

#pragma once
#include <QWidget>
#include <QListWidget>
#include <QListWidgetItem>
#include <QList>
#include <QCheckBox>
#include <QSet>

class FilterWidget :
	public QWidget
{
public:
	FilterWidget(QStringList Items, QStringList showItems, int col, QWidget *parent = 0);
	~FilterWidget();

	//获取要显示的列表
	QStringList getShowList();

	//获取列号
	int getColumn();

	//显示
	void exec(const QPoint &pos);

private slots:
	//勾选状态更改
	void slot_stateChanged();

private:

	QListWidget* m_ListWidget = nullptr;

	//要显示的项
	QStringList m_showList;

	//列号
	int m_col;
};


FilterWidget.cpp

#include "FilterWidget.h"

#include <QVBoxLayout>
#include <QEventLoop>

//Items:所有项
//showItems:显示的项
//col:列号
FilterWidget::FilterWidget(QStringList Items, QStringList showItems, int col, QWidget *parent/*=0*/):
	QWidget(parent),
	m_col(col)
{
	this->setFixedWidth(50);
	this->setFixedHeight(100);

	m_ListWidget = new QListWidget(this);
	
	QVBoxLayout* lay = new QVBoxLayout(this);
	lay->setMargin(0);
	lay->setSpacing(0);
	setLayout(lay);
	for each (QString var in Items)
	{
		QCheckBox* checkBox = new QCheckBox(this);
		checkBox->setText(var);
		if (showItems.contains(var))
		{
			m_showList.append(var);
			checkBox->setChecked(true);
		}
		connect(checkBox, &QCheckBox::stateChanged, this, &FilterWidget::slot_stateChanged);
		QListWidgetItem *item = new QListWidgetItem();
		m_ListWidget->addItem(item);
		m_ListWidget->setItemWidget(item,checkBox);
	}
	lay->addWidget(m_ListWidget);

}

FilterWidget::~FilterWidget()
{
}

QStringList FilterWidget::getShowList()
{
	return m_showList;
}

int FilterWidget::getColumn()
{
	return m_col;
}

void FilterWidget::exec(const QPoint & pos)
{
	setAttribute(Qt::WA_ShowModal, true);
	move(pos);
	show();
	QRect rect = geometry();
	QEventLoop loop;
	loop.exec();
}

void FilterWidget::slot_stateChanged()
{
	m_showList.clear();
	//遍历
	for (int i = 0; i < m_ListWidget->count(); i++)
	{
		//先获取QListWidgetItem
		QListWidgetItem *item = m_ListWidget->item(i);
		//找到第i个Item对应的CheckBox
		QCheckBox *checkBox = static_cast<QCheckBox *>(m_ListWidget->itemWidget(item));

		if (checkBox->isChecked())
			m_showList.append(checkBox->text());
	}
}


示例工程

  • 3
    点赞
  • 71
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值