QTableWidget 中插入QCheckBox复选框,状态判断,居中显示

在QTableWidget表格中显示一个QCheckBox:

第一种方法,QTableWidgetItem这个对象有CheckState属性,既能显示QCheckBox,又能读取状态。

QTableWidget *tableWidget = new QTableWidget;

QTableWidgetItem *checkBox = new QTableWidgetItem();
 checkBox->setCheckState(Qt::Checked);
 tableWidget ->setItem(2, 2, checkBox);

以上代码就在tablewidget中显示一个QCheckBox。但是如何判断复选框是否被选中呢,方法是利用QTableWidget::cellChanged()函数,检查单元格内容的变化,然后连接此信号,在槽函数中检测checkBox的状态。

connect(tableWidget, SIGNAL(cellChanged(int,int)), this, SLOT(changeTest(int, int)));

 void changeTest(int row, int col)

 {

     if(tableWidget ->item(row, col)->checkState() == Qt::Checked) //选中

         …

     else

         …

 }

不过这样的QCheckBox是左对齐的。如果想要让居中对齐就还是需要使用第二种方法。而且可以设置我们想要的checkbox的样式

第二种方法:void QTableWidget::setCellWidget(int row, int column, QWidget *widget),事实证明使用这个函数正常显示CheckBox没有问题

关于状态判断,可以借助 void setObjectName(const QString &name),通过 objectName,去设置和获取行列号

 pCheckBox->setObjectName(QString("%1_%2_%3_Itme").arg(table->objectName()).arg(row).arg(column));

拆解objectName,就可以获取到行和列。 

 QString objectName = check->objectName();
        QStringList nameList = objectName.split("_");//拆解
        if(nameList.count() == 4)
        {
            QString tableName = nameList.at(0);//表格名称
            int row = nameList.at(1).toInt();//行
            int column = nameList.at(2).toInt();//列
            bool checked = check->isChecked();//是否被选中
            
            //知道了表格、行、列,就可以执行我们所需要的操作了。。。
            qDebug() << QString("%1表第%2行第%3列是否被选中:%4")
                            .arg(tableName).arg(row).arg(column).arg(checked?"是":"否");

        }

有个坑需要注意:

当行列发生变化了,QCheckBox 不在原来的行和列了,需要同步更新 setObjectName,否则通过ObjectName 获取到的行和列是不正确的,严重的可能引起越界导致的崩溃问题

详细代码如下:
 


#include <QCheckBox>
#include <QTableWidget>
#include <QHBoxLayout>
#include <QDebug>
#include <QStyleFactory>

//获取CheckBox
QCheckBox* getCheckBox(QTableWidget*table,int row ,int column)
{
    QWidget* pWidget = 0;
    pWidget = table->cellWidget(row,column); //找到单元格
    QCheckBox *pCheckBox = 0;
    bool bNew = true;
    if(pWidget != 0) //
    {
        bNew = false;
    }
    if(bNew)
    {
        pWidget = new QWidget(table); //创建一个widget
        QHBoxLayout *hLayout = new QHBoxLayout(pWidget); //创建布局
        pCheckBox = new QCheckBox(pWidget);
        //根据objectName ,去拆解所属的tableWidget 、行、列
        pCheckBox->setObjectName(QString("%1_%2_%3_Itme").arg(table->objectName()).arg(row).arg(column));
        pCheckBox->setChecked(false);
        pCheckBox->setFont(table->font());
        pCheckBox->setFocusPolicy(Qt::NoFocus);
        pCheckBox->setStyle(QStyleFactory::create("fusion"));
        pCheckBox->setStyleSheet(QString(".QCheckBox {margin:3px;border:0px;}QCheckBox::indicator {width: %1px; height: %1px; }").arg(20));
        hLayout->addWidget(pCheckBox); //添加
        hLayout->setMargin(0); //设置边缘距离
        hLayout->setAlignment(pCheckBox, Qt::AlignCenter); //居中
        hLayout->setSpacing(0);
        pWidget->setLayout(hLayout); //设置widget的布局
        table->setCellWidget(row,column,pWidget);
    }
    QList<QCheckBox *> allCheckBoxs =  pWidget->findChildren<QCheckBox *>();
    if(allCheckBoxs.size() > 0)
        pCheckBox = allCheckBoxs.first();
    return pCheckBox;
}
//处理CheckBox
QCheckBox* setCheckBox(QTableWidget*table,int row ,int column,bool checkd)
{
    QCheckBox *check = getCheckBox(table,row,column);
    if(check != 0) //
    {
        check->setChecked(checkd);
    }
    QCheckBox::connect(check,&QCheckBox::stateChanged,[=]{
        QString objectName = check->objectName();
        QStringList nameList = objectName.split("_");//拆解
        if(nameList.count() == 4)
        {
            QString tableName = nameList.at(0);//表格名称
            int row = nameList.at(1).toInt();//行
            int column = nameList.at(2).toInt();//列
            bool checked = check->isChecked();//是否被选中
            
            //知道了表格、行、列,就可以执行我们所需要的操作了。。。
            qDebug() << QString("%1表第%2行第%3列是否被选中:%4")
                            .arg(tableName).arg(row).arg(column).arg(checked?"是":"否");

        }
    });
    return check;
}

具体使用,写了例子,

    ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    ui->tableWidget->setRowCount(4);
    ui->tableWidget->setColumnCount(4);
    for(int i =0; i <2; i++)
        for(int j =0; j <4; j++)
            setCheckBox(ui->tableWidget,i,j,false);
    for(int i =2; i <4; i++)
    {
        for(int j =0; j <4; j++)
        {
            QTableWidgetItem*item = new QTableWidgetItem();
            item->setTextAlignment(Qt::AlignCenter);
            item->setFont( ui->tableWidget->font());
            item->setCheckState(Qt::Checked);
             ui->tableWidget->setItem(i, j, item);
        }
    }

执行效果如下图:前两行是QCheckBox,后两行是 QTableWidgetItem这个对象有CheckState属性

第二种方法的CheckBox不仅可以居中,可以设置框的大小。通过样式进行设置。用fusion风格

pCheckBox->setStyle(QStyleFactory::create("fusion"));


QCheckBox::indicator {width: 20px; height:20px; }

getCheckBox函数返回的QCheckBox* 指针,有了指针就可以绑定信号和槽,当状态修改了,触发信号时,槽就会执行了

补充一下:有评论说不需要使用setObjectName,除了评论的方式,下面再介绍另外两种不使用setObjectName的方式,获取到改变的对应数据

方式1:通过坐标转为QModelIndex,从而获取到对应的行和列,知道行列就能确定是哪一条数据变了

QCheckBox *check = getCheckBox(table,row,column);
connect(check, &QCheckBox::stateChanged, [=] {
			int x = check->parentWidget()->frameGeometry().x();
			int y = check->parentWidget()->frameGeometry().y();
			QModelIndex index = table->indexAt(QPoint(x, y));
			int row_current = index.row();
			int row_column = index.column();
            // 后面就根据行列找到数据
       });

方式2:QObject中有这两个函数,可以设置用户自己的数据,我们借助这两个函数来实现


    void setUserData(uint id, QObjectUserData* data);
    QObjectUserData* userData(uint id) const;

比如:每一行记录都有一个唯一的ID,我们实现一个记录ID的类(如果参数是非int型,或者有多个参数,可以参考自定义一个继承QObjectUserData的类就行)

class IDUserData : public QObjectUserData {
public:
    IDUserData(const int& id) : m_id(id) {}
    int id() const { return m_id; }

private:
    int m_id;
};

 唯一的ID设置为check的自定义用户数据,然后触发信号时,直接根据这个唯一的ID去确定是哪一条数据发生了改变,然后就跳过了行列的步骤了。

QCheckBox *check = getCheckBox(table,row,column);
check->setUserData(Qt::UserRole + 1, new IDUserData(id));
connect(check, &QCheckBox::stateChanged, [=] {
     // getFilter 函数功能是 :根据 id, 去找到我们的记录,具体就不展开了
     IDUserData* data = static_cast<IDUserData*>(check->userData(Qt::UserRole + 1));
     auto filter = getFilter(data->id());
     if (filter)
     {
         //找到后,就可以做我们想要的操作处理了,比如把修改后的值保存到数据库等等
         //....
     }
     });

  • 29
    点赞
  • 226
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值