先来看效果,在tablewidget表头第一列有一个checkbox选择框
这个选择框实现对下面所有项的全选功能
需要自定义表头类继承HeaderView
自定义表头类
MyHeaderView.h
#ifndef MYHEADERVIEW_H
#define MYHEADERVIEW_H
#include <QHeaderView>
#include <QtGui>
#include <QPainter>
#include <QStyleOptionButton>
#include <QStyle>
#include <QCheckBox>
#include <QEvent>
#include <QMouseEvent>
#include <QStringList>
#include <QPushButton>
using namespace std;
class MyHeaderView : public QHeaderView
{
Q_OBJECT
public:
MyHeaderView( QPoint topLeft, QSize size,
Qt::Orientation orientation, QWidget *parent = nullptr);
protected:
///
/// \brief paintSection 绘制表头
/// \param painter
/// \param rect rect是表头第一列的大小画复选框的列,
/// \param logicalIndex 表示表头第几列,0表示第0列
///
void paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const;
///
/// \brief mousePressEvent 表头上按下鼠标按钮时
/// \param event
///
void mousePressEvent(QMouseEvent *event);
public:
void setCheckState(bool state); //设置复选框状态
QStringList HeaderContent() const; //m_HeaderContent get方法
void setHeaderContent(const QStringList &HeaderContent); //m_HeaderContent 的set方法
signals:
void signalCheckStateChanged(bool state); //勾选状态发生改变信号
private:
QPoint topLeft ; //勾选框起始屏幕坐标
QSize boxSize ; //勾选框大小
bool isChecked ; //勾选框状态
bool isPlateNameDown ; //压板名称列
QStringList m_HeaderContent;
QCheckBox *check ;
QPushButton *button_plate_name ;
};
#endif // MYHEADERVIEW_H
MyHeaderView.cpp
#include "MyHeaderView.h"
MyHeaderView::MyHeaderView(QPoint topLeft, QSize size, Qt::Orientation orientation, QWidget *parent)
: QHeaderView(orientation, parent), topLeft(topLeft), boxSize(size), isChecked(false)
{
check = new QCheckBox ;
button_plate_name = new QPushButton;
button_plate_name->setObjectName("HeaderPushButton");
button_plate_name->setText("压板名称");
}
void MyHeaderView::setCheckState(bool state)
{
isChecked = state;
}
QStringList MyHeaderView::HeaderContent() const
{
return m_HeaderContent;
}
void MyHeaderView::setHeaderContent(const QStringList &HeaderContent)
{
m_HeaderContent = HeaderContent;
}
void MyHeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalIndex) const
{
painter->save();
QHeaderView::paintSection(painter, rect, logicalIndex);
painter->restore();
if (logicalIndex == 0)
{
QStyleOptionButton option;
// 计算复选框居中显示的位置
int x = rect.x() + (rect.width() - boxSize.width()) / 2;
int y = rect.y() + (rect.height() - boxSize.height()) / 2;
option.rect = QRect(x, y, boxSize.width(), boxSize.height());
option.state = isChecked ? QStyle::State_On : QStyle::State_Off;
// 设置复选框样式
QString sheet = QString("QCheckBox::indicator {width: %1px; height: %2px;}").arg(boxSize.width()).arg(boxSize.height());
check->setStyleSheet(sheet);
// 绘制复选框
this->style()->drawControl(QStyle::CE_CheckBox, &option, painter, check);
}
}
void MyHeaderView::mousePressEvent(QMouseEvent *event)
{
int col = visualIndexAt(event->pos().x());
if (col == 0)
{
isChecked = !isChecked;
this->updateSection(0);
emit signalCheckStateChanged(isChecked);
}
// 手动发送 sectionClicked 信号
emit QHeaderView::sectionClicked(visualIndexAt(event->pos().x()));
QHeaderView::mousePressEvent(event);
}
在主界面 .h 包含自定义的表头类名称。这里初始化表格函数里面使用
#ifndef CONFIGURATIONMAINTAINFORM_H
#define CONFIGURATIONMAINTAINFORM_H
#include <QWidget>
#include <QDebug>
#include <QListView>
#include <QStandardItemModel>
#include <QFont>
#include <QIcon>
#include <QPushButton>
#include <QHBoxLayout>
#include <QDialog>
#include <QPoint>
#include <QAction>
#include <QTreeWidgetItem>
#include <QTreeWidgetItemIterator>
#include "MyHeaderView.h" //必须包含自定义的表头类
namespace Ui {
class ConfigurationMaintainForm;
}
class ConfigurationMaintainForm : public QWidget
{
Q_OBJECT
public:
explicit ConfigurationMaintainForm(QWidget *parent = nullptr);
~ConfigurationMaintainForm();
private:
///
/// \brief InitDisplayTablewidget 初始化表格
///
void InitDisplayTablewidget();
private slots:
///
/// \brief slot_onHeaderClicked 表头被点击
/// \param state
///
void slot_onHeaderClicked(bool state);
///
/// \brief onHeaderClicked 需要修改数据的表头
///
void onHeaderClicked(int col);
///
/// \brief onCheckBoxStateChanged checkbox状态改变
/// \param state
///
void onCheckBoxStateChanged(int state);
private:
Ui::ConfigurationMaintainForm *ui;
MyHeaderView *myHeader ;//自定义表头checkbox
QList <int>line_number ;//获取列表中所勾选的行数
bool m_bChecked ;//勾选状态
};
#endif // CONFIGURATIONMAINTAINFORM_H
主界面.cpp
#include "ConfigurationMaintainForm.h"
#include "ui_ConfigurationMaintainForm.h"
ConfigurationMaintainForm::ConfigurationMaintainForm(QWidget *parent) :
QWidget(parent),
ui(new Ui::ConfigurationMaintainForm)
{
ui->setupUi(this);
//初始化右侧表格
this->InitDisplayTablewidget();
}
void ConfigurationMaintainForm::InitDisplayTablewidget()
{
//表头填充
m_table_h_headers << " "<<"序号"<<"压板名称"<<"行"<<"列"<<"基准值设置"<<"汇聚模块IP"<<"汇聚模块\n采集序号"<<"压板类别"
<<"压板所属保护\n装置IEDNAME"<<"压板所属保护装置实物ID"<<"保护装置名称" <<"横线槽产品型号" <<"压板英文" << "压板型号" <<"采集地址";
QStringList temp_header ;
temp_header<<"序号"<<"压板名称"<<"行"<<"列"<<"基准值设置"<<"汇聚模块IP"<<"汇聚模块\n采集序号"<<"压板类别"<<"压板所属保护\n装置IEDNAME"<<"压板所属保护装置实物ID"<<"保护装置名称";
ui->tableWidget_Maintain->setColumnCount(m_table_h_headers.count()) ; // 设置列数
ui->tableWidget_Maintain->setHorizontalHeaderLabels(m_table_h_headers); //设置表头信息
// 创建并设置自定义表头 checkbox
myHeader = new MyHeaderView(QPoint(40, 10),QSize(20, 20),Qt::Horizontal,ui->tableWidget_Maintain);
ui->tableWidget_Maintain->setHorizontalHeader(myHeader) ;
myHeader->setHeaderContent(temp_header) ;
//表头被点击后发出信号。主界面改变所有复选框的状态
connect(myHeader, &MyHeaderView::signalCheckStateChanged, [=](bool state)
{
slot_onHeaderClicked(state);
});
//设置列表最后一列填充满
// ui->tableWidget_Maintain->horizontalHeader()->setStretchLastSection(true);
ui->tableWidget_Maintain->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
//设置是否显示格子线
//ui->tableWidget_Maintain->setShowGrid(false);
ui->tableWidget_Maintain->setGridStyle(Qt::NoPen); // 设置网格线风格为没有笔触(显示列线)
//隐藏垂直表头
ui->tableWidget_Maintain->verticalHeader()->setVisible(false);
//必须先清空表格显示内容
ui->tableWidget_Maintain->clearContents();
connect(ui->tableWidget_Maintain->horizontalHeader(), SIGNAL(sectionClicked(int)),
this, SLOT(onHeaderClicked(int)));
}
void ConfigurationMaintainForm::slot_onHeaderClicked(bool state)
{
// 设置所有复选框的状态
int rowCount = ui->tableWidget_Maintain->rowCount();//获取行数
for (int i = 0; i < rowCount; ++i)
{
QCheckBox *pCheckBox = getCheckBox(i); // 获取第一列中的复选框
if (pCheckBox)
{
pCheckBox->setChecked(state);
}
}
}
void ConfigurationMaintainForm::onHeaderClicked(int col)
{
if(col == 0 || col == 1 ||col == 5 ||col == 6)
{
return;
}
this->SetTableWidgetItemNoEdit();
for(int i=0; i<ui->tableWidget_Maintain->rowCount(); i++)
{
QTableWidgetItem *item = ui->tableWidget_Maintain->item(i,col);
if(item)
{
item->setFlags(Qt::ItemIsEnabled |Qt::ItemIsEditable);
}
}
}
void ConfigurationMaintainForm::onCheckBoxStateChanged(int state)
{
QCheckBox *checkBox = qobject_cast<QCheckBox*>(sender());
// 获取复选框所在的单元格的行索引
QPoint checkBoxPos = checkBox->mapToGlobal(QPoint(0, 0));
QPoint tableWidgetPos = ui->tableWidget_Maintain->viewport()->mapFromGlobal(checkBoxPos);
int row = ui->tableWidget_Maintain->rowAt(tableWidgetPos.y());
if (state == Qt::Checked)
{
if (!line_number.contains(row))
{ // 防止重复添加行号
line_number << row;
}
}
else
{
line_number.removeOne(row);
}
// 清除所有选中的单元格
ui->tableWidget_Maintain->clearSelection();
// 重新选中 hangshu 中的行,并设置高亮颜色
for (int row : line_number)
{
QTableWidgetSelectionRange range(row, 0, row, ui->tableWidget_Maintain->columnCount() - 1);
ui->tableWidget_Maintain->setRangeSelected(range, true);
}
// 设置高亮颜色为蓝色
QBrush brush(QColor("#0078d7"));
QPalette pal = ui->tableWidget_Maintain->palette();
pal.setBrush(QPalette::Highlight, brush);
ui->tableWidget_Maintain->setPalette(pal);
}
表格内每行插入数据时候也要插入checkbox。所以在每次插入一行数据的位置第一列先放入一个复选框
//第一列设置复选框
QWidget *checkBoxWidget = new QWidget() ;
QCheckBox *checkBox = new QCheckBox() ;
m_Display_Maintain_CheckBox_List.append(checkBox);
//复选框状态改变槽函数
connect(checkBox, &QCheckBox::stateChanged, this, &ConfigurationMaintainForm::onCheckBoxStateChanged);
// 设置布局,使复选框居中显示
QHBoxLayout *layoutCheckBox = new QHBoxLayout(checkBoxWidget);
layoutCheckBox->addWidget(checkBox) ;
layoutCheckBox->setAlignment(Qt::AlignCenter) ;
layoutCheckBox->setContentsMargins(0, 0, 0, 0) ;
ui->tableWidget_Maintain->setCellWidget(row, 0, checkBoxWidget);