Qt 自定义表格(表头)

搬砖的过程中中,我们经常会遇到定制化的表格,比如表头的第一列为全选复选框,或者需要依赖表头的某一咧进行排序,当然,排序这个原有的QTableWidget已经实现了功能,但是如果需要在该列的表头添加icon图片,则会显得比较麻烦。

因此,自定义表格的实现还是显得比较重要,我们使用两个去除原有表头的QTableWidget来实现自定义表格,使我们在平常的使用过程中显得比较方便。

相对来说,组合表格实现的方式还是比较简单的,首先我们先看下表头的首列为全选复选框时,我们怎么创建单元格。

QWidget* TableWidget::newBtnCheckBox(const QString& text, const QString& name)
{
    auto pBtnCheck = new QCheckBox(text);
    pBtnCheck->setObjectName(name);
    pBtnCheck->setFixedSize(72, 36);

    auto pWidget = new QWidget;
    auto layout = new QHBoxLayout;
    layout->setSpacing(0);
    layout->setMargin(0);
    layout->addWidget(pBtnCheck);
    pWidget->setLayout(layout);
    return pWidget;
}

看起来还是比较中规中矩的,但是一般来说,表头的复选框被选中或者取消勾选时,往往会存在一个问题就是,表体的所有复选框会相应的被全选或者取消,这整个过程中,我们首先想到的第一个方案就是当表头的复选框被点击时,遍历表体的所有第一列进行相同的操作,这样一来,如果表体的数据比较少,我们基本上是没什么感知的,一但表体的数据比较多,假设有上千行,甚至更多,那么我我们就能够很容易看见表体的复选框被一个个改变状态。并且在改变状态的过程中,UI线程是被阻塞的,整个界面看起来就会比较卡顿,所以这种方式可以选择在数据量较少的情况下适用。

为了改善这个缺点,我们只能另辟蹊径,找找其他的方式,看一看能够在点击表头复选框的时候,表体的复选框同时被改变状态,我们首先想到就是表体的每个复选框都和表头的复选框进行信号槽的关联,这样当表头的复选框被点击时,同时发送信号,表体的复选框就能直接相应槽函数进行各自状态的改变。其次想到的是。。。(其实也没想)

所以在创建QCheckBox的时候增加以下代码:

auto pWidgetAll = static_cast<QWidget*>(ui->tbHeader->cellWidget(0, 0));
if(Q_NULLPTR != pWidgetAll)
{
    //to do something...
}
auto pBtnAll = pWidgetAll->findChild<QCheckBox*>(QString("btnCheck"));
if(Q_NULLPTR != pBtnAll )
{
    //to do something...
}
connect(pBtnAll, &QCheckBox::clicked, pBtnCheck, &QCheckBox::setChecked);

进行信号槽关联。注意一点,创建表头复选框的时候,需要进行屏蔽

如果我们需要在表头的其他列需要点击进行排序,或者其他的操作,根据上面的操作,能够很方便的得到想要的方案。下面是需要在表头的某一列增加排序的方案。

QWidget* TableWidget::newTbHeaderCellWidget(const QString& text, const QString& name, const QString& property, const QString& value)
{
    auto pBtn = new QPushButton;
    pBtn->setObjectName(name);
    pBtn->setFixedSize(100, 24);
    pBtn->setProperty(property, value);
    pBtn->setText(text);
    pBtn->setLayoutDirection(Qt::RightToLeft);

    auto* pWidget = new QWidget;
    auto* layout = new QHBoxLayout;
    
    layout->setSpacing(0);
    layout->setMargin(0);
    layout->addWidget(pBtn);
    pWidget->setLayout(layout);
    return pWidget;
}

上面的函数定义,我们给了4个入参,前面的两个应该比较好理解,后面的两个其实也是比较好理解的,如果表头有不同的操作,并且显示的icon也不一样的时候,我们就能够通过设置不同的属性来让按钮显示不同的icon,尽量达到代码的复用,搬砖的我们一定要学会偷懒。

icon设置之后,默认显示是在按钮的左边,右边是文字,我们可以通过setLayoutDirection方法来改变显示的方向。

接下来,也是比较重要的一点,Qt原生的QTableWidget窗体是一个比较复杂的控件,每一个QTableWidgetItem其实都是一个小窗体,在插入数据的过程中,我们每插入一个QTableWidgetItem时,都会触发窗体的重绘事件进行窗体的绘制,这样存在的问题是,如果我们的数据量比较大,会造成界面的卡顿,而且效果会比较明显,所以在插入数据前,我们可以通setUpdatesEnabled 方法来设置表格不进行绘制,数据插入完成后,再绘制一次窗口就行。

void TableWidget::insertData(const QList<QStringList> data)
{
     ui->tbBody->setRowCount(data.size());
     ui->tbBody->setUpdatesEnabled(false);
     
     for(int nIndex = 0; nIndex < data.size(); ++nIndex)
     {
         QStringList row = data[nIndex];
         for(int nRet = 0; nRet < row.size(); ++nRet)
         {
             ui->tbBody->setItem(nIndex, nRet + 1, new QTableWidgetItem(row.at(nRet)));
         }
     }

     ui->tbBody->setUpdatesEnabled(true);
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值