【QT】学习之TableWidget设置自定义表头checkbox选择

先来看效果,在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);

要将Qt的TreeWidget设置为复选框样式,可以使用setItemWidget()函数将QCheckBox添加到对应的TreeWidgetItem中。下面是一个示例代码: ```cpp // 创建一个带有复选框的QTreeWidgetItem QTreeWidgetItem* item = new QTreeWidgetItem(); QCheckBox* checkBox = new QCheckBox(); item->setText(0, "Item 1"); ui->treeWidget->addTopLevelItem(item); ui->treeWidget->setItemWidget(item, 0, checkBox); // 将选中的项添加到TableWidget表头中 connect(ui->pushButton, &QPushButton::clicked, [=](){ for(int i = 0; i < ui->treeWidget->topLevelItemCount(); i++){ QTreeWidgetItem* item = ui->treeWidget->topLevelItem(i); QCheckBox* checkBox = qobject_cast<QCheckBox*>(ui->treeWidget->itemWidget(item, 0)); if(checkBox && checkBox->isChecked()){ // 添加到TableWidget表头QTableWidgetItem* tableItem = new QTableWidgetItem(item->text(0)); ui->tableWidget->setHorizontalHeaderItem(i, tableItem); } } }); ``` 在上述代码中,我们首先创建了一个带有复选框的TreeWidgetItem,并将其添加到TreeWidget中。然后,我们使用setItemWidget()函数将QCheckBox添加到对应的TreeWidgetItem中。 接着,我们创建一个按钮,并在其点击事件中遍历TreeWidget中的所有顶级项,判断其对应的复选框是否被选中。如果被选中,我们就将该项的文本添加到TableWidget表头中。这里使用了qobject_cast()函数将TreeWidgetItem对应的QWidget转换为QCheckBox。 注意,在将选中项添加到TableWidget中时,我们使用了setHorizontalHeaderItem()函数。这个函数可以将一个QTableWidgetItem添加到TableWidget表头中,其中第一个参数是列号,第二个参数是要添加的QTableWidgetItem。因此,我们可以将TreeWidget中选中的项的文本添加到TableWidget的对应列中。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值