最近在做表格,用QTableView,然后有一个需求是给表格添加表头,但是没有一个API能够在表头添加复选框,基本都是来重载QHeaderView,有两种方法:
1. 重载paintSection这里参考QTableView表头添加QCheckBox复选框_未来之歌-CSDN博客_qtableview表头添加复选框
主要是重载paintSection和mousePressEvent这两个函数
headview.h
#ifndef HEADERVIEW_H #define HEADERVIEW_H #include#include #include #include #include #include class HeaderView : public QHeaderView { Q_OBJECT public: //构造函数, 第一个参数设定表头方向 HeaderView(Qt::Orientation orientation, QWidget* parent = 0); protected: void paintSection(QPainter* painter, const QRect& rect, int logicalIndex) const; void mousePressEvent(QMouseEvent* event); signals: // 复选框状态改变 void checkStateChange(int state); public slots: // 设置复选框的状态 void slot_setCheckState(Qt::CheckState state); private: //checkbox的开启或关闭状态 bool isOn; QCheckBox* checkBox; }; #endif // HEADERVIEW_H
headerview.cpp
#include "headerview.h"
HeaderView::HeaderView(Qt::Orientation orientation, QWidget* parent)
: QHeaderView(orientation, parent)
{
}
void HeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if(logicalIndex == 0)
{
QStyleOptionButton option;
option.iconSize = QSize(10,10);
option.rect = rect;
if(isOn)
option.state = QStyle::State_On;
else
option.state = QStyle::State_Off;
this->style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter);
}
}
void HeaderView::mousePressEvent(QMouseEvent *event)
{
if (isOn) {
emit checkStateChange(Qt::CheckState::Unchecked);
isOn = false;
} else {
emit checkStateChange(Qt::CheckState::Checked);
isOn = true;
}
this->viewport()->update();
QHeaderView::mousePressEvent(event);
}
void HeaderView::slot_setCheckState(Qt::CheckState state)
{
checkBox->setCheckState(state);
}
这里的这个paintSection,是对每一段进行一个绘制。
logicalIndex == 0是代表是表头的第一列。
State_On和State_Off分别代表开关状态。
this->style()->drawPrimitive这个是一个用于绘画各种基本元素的函数,参考Styles Example | Qt Widgets 5.15.8,这个函数是QStyle类的一个纯虚函数,由其他继承自QStyle的子类去实现自己的样式。然后QStrle::PE_IndicatoeCheckBox代表画的是一个复选框。
mousePressEvent这是一个鼠标点击事件。
2. 重载updateGeometries上面这种重载paintSection的方法,我自己使用之后,发现好像有点延迟,所以就找了另外一种方法,这种方法是直接设置位置,使用的是Qt自己的QCheckBox,反应好像更快了。
headview.h
#ifndef HEADERVIEW_H #define HEADERVIEW_H #include#include #include #include #include class HeaderView : public QHeaderView { Q_OBJECT public: //构造函数, 第一个参数设定表头方向 HeaderView(Qt::Orientation orientation, QWidget* parent = 0); protected: void updateGeometries(); signals: void checkStateChange(int state); public slots: void slot_setCheckState(Qt::CheckState state); private: QCheckBox* checkBox; }; #endif // HEADERVIEW_H
headerview.cpp
#include "headerview.h"
HeaderView::HeaderView(Qt::Orientation orientation, QWidget* parent)
: QHeaderView(orientation, parent)
{
checkBox = new QCheckBox("全选", this);
checkBox->show();
connect(checkBox, &QCheckBox::clicked, [this] () {
emit checkStateChange(checkBox->checkState());
});
}
void HeaderView::updateGeometries()
{
checkBox->move(sectionPosition(0) + 19, 6);
}
void HeaderView::slot_setCheckState(Qt::CheckState state)
{
checkBox->setCheckState(state);
}
连接信号,当鼠标点击QCheckBox时,发射信号。updateGeometries这个函数,就是移动QCheckBox
最终效果如下图:



