QT QTableView 表头添加复选框
最近在做表格,用QTableView,然后有一个需求是给表格添加表头,但是没有一个API能够在表头添加复选框,基本都是来重载QHeaderView,有两种方法:
1. 重载paintSection
这里参考QTableView表头添加QCheckBox复选框_未来之歌-CSDN博客_qtableview表头添加复选框
主要是重载paintSection 和mousePressEvent 这两个函数
headview.h
#ifndef HEADERVIEW_H
#define HEADERVIEW_H
#include <QObject>
#include <QHeaderView>
#include <QPainter>
#include <QCheckBox>
#include <QObject>
#include <QDebug>
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:
bool isOn;
QCheckBox* checkBox;
};
#endif
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 <QObject>
#include <QHeaderView>
#include <QPainter>
#include <QCheckBox>
#include <QObject>
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.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
最终效果如下图:
|