一、重写QHeaderView
通过重写QHeaderView中的paintSection()方法来实现在QTableWidget组件的表头中插入复选框的功能。
重写函数为:void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override
原理是QTableWidget使用MyHeaderView添加表头时,通过QPainter的重绘功能,在添加表头的过程中对表头列绘制复选框,并通过重写鼠标的点击事件,获取复选框的状态,通过信号和槽的方式完成想要完成的动作。
MyHeaderView.h头文件
#ifndef MyTableWidget_H
#define MyTableWidget_H
#include <QtWidgets>
class MyHeaderView : public QHeaderView
{
Q_OBJECT
public:
MyHeaderView(Qt::Orientation orientation,
QWidget * parent = nullptr) :
QHeaderView(orientation, parent)
{
setSectionsClickable(true);
}
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override;
void mousePressEvent(QMouseEvent* event) override;
private:
void checkBoxStateChanged(int pos);
signals:
void checkBoxChangedIndex(int);
private:
Qt::CheckState triState1 = Qt::Unchecked;
Qt::CheckState triState2 = Qt::Unchecked;
};
#endif // MyTableWidget_H
MyHeaderView .cpp源文件
#include "MyTableWidget.h"
void MyHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == 1)
{
QStyleOptionButton option;
option.initFrom(this);
option.rect = QRect(rect.x()/* + 10*/, rect.y() + 10, 18, 18);
option.features = QStyleOptionButton::None;
if (triState1 == Qt::Checked)
option.state |= QStyle::State_On;
else if (triState1 == Qt::PartiallyChecked)
option.state |= QStyle::State_NoChange;
else
option.state |= QStyle::State_Off;
style()->drawControl(QStyle::CE_CheckBox, &option, painter/*, checkBox*/);
}
else if (logicalIndex == 2) {
QStyleOptionButton option;
option.initFrom(this);
option.rect = QRect(rect.x()/* + 10*/, rect.y() + 10, 18, 18);
option.features = QStyleOptionButton::None;
if (triState2 == Qt::Checked)
option.state |= QStyle::State_On;
else if (triState2 == Qt::PartiallyChecked)
option.state |= QStyle::State_NoChange;
else
option.state |= QStyle::State_Off;
style()->drawControl(QStyle::CE_CheckBox, &option, painter/*, checkBox*/);
}
}
void MyHeaderView::mousePressEvent(QMouseEvent* event)
{
if (event->button() == Qt::LeftButton) {
if (logicalIndexAt(event->pos()) == 1) {
switch (triState1) {
case Qt::Unchecked:
triState1 = Qt::Checked;
break;
case Qt::Checked:
triState1 = Qt::Unchecked;
break;
}
updateSection(1);
}
else if (logicalIndexAt(event->pos()) == 2) {
switch (triState2) {
case Qt::Unchecked:
triState2 = Qt::Checked;
break;
case Qt::Checked:
triState2 = Qt::Unchecked;
break;
}
updateSection(2);
}
checkBoxStateChanged(logicalIndexAt(event->pos()));
}
QHeaderView::mousePressEvent(event);
}
void MyHeaderView::checkBoxStateChanged(int pos)
{
emit checkBoxChangedIndex(pos);
}
paintSection()方法是QTableWidget在绘制表头的时候自动调用的,其中的logicalIndex参数为表头中的列的索引值。
上述示例中为表头的第二列和第三列添加复选框,单独用triState1和triState2来管理,通过信号和槽传递关键信息做下一步处理
二、引用和使用
QTableWidget *qTableWidget = new QTableWidget();
qTableWidget->setColumnCount(3);
MyHeaderView *qMyHeaderView = new MyHeaderView(Qt::Horizontal, qTableWidget);
connect(qMyHeaderView, &MyHeaderView::checkBoxChangedIndex, this, &OiDataAnsysTest::changeAllColumnCheckBoxState);
qTableWidget->setHorizontalHeader(qMyHeaderView);
qTableWidget->setHorizontalHeaderLabels(QStringList() << "Column1" << "Column2" << "Column3");