头文件
#ifndef CHECKBOXHEADERVIEW_H
#define CHECKBOXHEADERVIEW_H
#include <QHeaderView>
class CheckBoxHeaderView : public QHeaderView
{
Q_OBJECT
public:
explicit CheckBoxHeaderView(Qt::Orientation orientation, QWidget *parent = nullptr);
~CheckBoxHeaderView();
protected:
bool event(QEvent *event);
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
void mousePressEvent(QMouseEvent *event);
void mouseReleaseEvent(QMouseEvent *event);
public slots:
void onStateChanged(int state);
private:
bool m_bPressed;
bool m_bChecked;
bool m_bTristate;
bool m_bNoChange;
bool m_bMoving;
signals:
void stateChanged(int state);
};
#endif // CHECKBOXHEADERVIEW_H
源文件
#include "checkboxheaderview.h"
#include <QPainter>
#include <QMouseEvent>
#include <QCheckBox>
#define CHECK_BOX_COLUMN 1
CheckBoxHeaderView::CheckBoxHeaderView(Qt::Orientation orientation, QWidget *parent)
: QHeaderView(orientation, parent),//m_isOn(false),
m_bPressed(false),
m_bChecked(false),
m_bTristate(false),
m_bNoChange(false),
m_bMoving(false)
{
setSectionsClickable(true);
}
CheckBoxHeaderView::~CheckBoxHeaderView()
{
}
void CheckBoxHeaderView::onStateChanged(int state)
{
if (state == Qt::PartiallyChecked) {
m_bTristate = true;
m_bNoChange = true;
}
else {
m_bNoChange = false;
}
m_bChecked = (state != Qt::Unchecked);
update();
}
void CheckBoxHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == CHECK_BOX_COLUMN)//第一列
{
QStyleOptionButton option;
option.initFrom(this);
if (m_bChecked)
option.state |= QStyle::State_Sunken;
if (m_bTristate && m_bNoChange)
option.state |= QStyle::State_NoChange;
else
option.state |= m_bChecked ? QStyle::State_On : QStyle::State_Off;
if (testAttribute(Qt::WA_Hover) && underMouse()) {
if (m_bMoving)
option.state |= QStyle::State_MouseOver;
else
option.state &= ~QStyle::State_MouseOver;
}
QPalette palette;
palette.setColor(QPalette::Background, QColor(0,0,0,100));
QCheckBox checkBox;
option.iconSize = QSize(20, 20);
option.rect = QRect(rect.left()+(rect.width()-checkBox.sizeHint().width())/2,
rect.top()+(rect.height()-checkBox.sizeHint().height())/2,
checkBox.sizeHint().width(), checkBox.sizeHint().height());
// style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &option, painter, &checkBox);
option.palette = palette;
style()->drawControl(QStyle::CE_CheckBox, &option, painter, &checkBox);
}
}
void CheckBoxHeaderView::mousePressEvent(QMouseEvent *event)
{
int nColumn = logicalIndexAt(event->pos());
if ((event->buttons() & Qt::LeftButton) && (nColumn == CHECK_BOX_COLUMN))
{
m_bPressed = true;
}
else
{
QHeaderView::mousePressEvent(event);
}
}
void CheckBoxHeaderView::mouseReleaseEvent(QMouseEvent *event)
{
if (m_bPressed)
{
if (m_bTristate && m_bNoChange)
{
m_bChecked = true;
m_bNoChange = false;
}
else
{
m_bChecked = !m_bChecked;
}
update();
Qt::CheckState state = m_bChecked ? Qt::Checked : Qt::Unchecked;
emit stateChanged(state);
updateSection(CHECK_BOX_COLUMN);
}
else
{
QHeaderView::mouseReleaseEvent(event);
}
m_bPressed = false;
}
bool CheckBoxHeaderView::event(QEvent *event)
{
// updateSection(0);
// if (event->type() == QEvent::Enter || event->type() == QEvent::Leave)
// {
// QMouseEvent *pEvent = static_cast<QMouseEvent *>(event);
// int nColumn = logicalIndexAt(pEvent->x());
// if (nColumn == CHECK_BOX_COLUMN)
// {
// m_bMoving = (event->type() == QEvent::Enter);
// update();
// return true;
// }
// }
return QHeaderView::event(event);
}
添加样式
checkBox.setProperty("stylesheet","default");
样式qss
QCheckBox[stylesheet='default']
{
color: white;
background: transparent;
}
QCheckBox[stylesheet='default']::indicator:disabled:unchecked,
QCheckBox[stylesheet='default']::indicator:enabled:unchecked
{
image: url(:/assets/images/icon_options.png);
}
QCheckBox[stylesheet='default']::indicator:disabled:checked,
QCheckBox[stylesheet='default']::indicator:enabled:checked
{
image: url(:/assets/images/icon_selected.png);
}
使用示例
CheckBoxHeaderView* checkBoxHeader = new CheckBoxHeaderView(Qt::Horizontal, ui->tableWidget);
checkBoxHeader->setStretchLastSection(true);
checkBoxHeader->setStyleSheet("alignment: left;");
QObject::connect(checkBoxHeader, &CheckBoxHeaderView::stateChanged, this, &DeviceManageForm::onCheckBoxHeaderStateChanged);
ui->tableWidget->setHorizontalHeader(checkBoxHeader);
参考文章
/**
* QTableWidget自定义表头QHeaderView加全选复选框
* https://blog.csdn.net/qq_43113326/article/details/101020715
* QTableView插入QCheckBox复选框
* https://blog.csdn.net/mj348940862/article/details/124475266
*/