@scopchanov 的解决方案对我不起作用,因为复选框涵盖了标题的整个项目

一种可能的解决方案是绘制带有样式的 CheckBox,但除此之外,您必须记住该元素是否被选中,为此我们使用QMap<>
第一个元素,logicalIndex
因为即使移动它也不会改变列和第二个元素是状态。
#include <QApplication>
#include <QHeaderView>
#include <QMouseEvent>
#include <QPainter>
#include <QStandardItemModel>
#include <QTableView>
class CheckedHeaderView : public QHeaderView
{
Q_OBJECT
public:
using QHeaderView::QHeaderView;
protected:
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const override
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
QStyleOptionButton opt;
QRect checkbox_rect = style()->subElementRect(QStyle::SE_CheckBoxIndicator, &opt);
checkbox_rect.moveCenter(rect.center());
opt.rect = checkbox_rect;
opt.state = QStyle::State_Enabled | QStyle::State_Active;
if(logicalIndex == columnDown)
opt.state |= QStyle::State_Sunken;
if (states[logicalIndex])
opt.state |= QStyle::State_On;
else
opt.state |= QStyle::State_Off;
style()->drawPrimitive(QStyle::PE_IndicatorCheckBox, &opt, painter);
}
void mousePressEvent(QMouseEvent *event) override
{
QHeaderView::mousePressEvent(event);
int li = logicalIndexAt(event->pos());
if(li == -1) return;
columnDown = li;
updateSection(li);
}
void mouseReleaseEvent(QMouseEvent *event) override
{
QHeaderView::mouseReleaseEvent(event);
int li = logicalIndexAt(event->pos());
if(li == -1) return;
states[li] = !states[li];
Q_EMIT checked(li, states[li]);
columnDown = -1;
updateSection(li);
}
Q_SIGNALS:
void checked(int logicalIndex, bool state);
private:
QMap<int, bool> states;
int columnDown = -1;
};
class TableView : public QTableView
{
Q_OBJECT
public:
TableView(QWidget *parent = nullptr):
QTableView(parent)
{
CheckedHeaderView *header = new CheckedHeaderView(Qt::Horizontal, this);
setHorizontalHeader(header);
connect(header, &CheckedHeaderView::checked, this, &TableView::on_checked);
}
private Q_SLOTS:
void on_checked(int logicalIndex, bool state){
QItemSelectionModel::SelectionFlags command = state? QItemSelectionModel::Select : QItemSelectionModel::Deselect;
for(int r=0; r < model()->rowCount(); r++){
QModelIndex ix = model()->index(r, logicalIndex);
selectionModel()->select(ix, command);
}
}
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TableView w;
QStandardItemModel *model = new QStandardItemModel(8, 6, &w);
w.setModel(model);
w.show();
return a.exec();
}
