【QT常用技术讲解】QTableView添加QCheckBox、QPushButton

前言

        QT展示列表信息的时候通常用到列表(比如用户信息、机构信息、设备信息等菜单),当需要对某列进行修改、删除操作时,就需要加入按钮(QPushButton),当需要对多列进行右键菜单操作时,就需要加入QCheckBox和右键菜单功能,本篇即围绕QTableView、QCheckBox、QPushButton,以及右键菜单进行讲解。

功能显示效果图

功能讲解

1、创建QTableView

(1)创建QTableView列表头

//两种方式创建列表头
    //1、在UI中之间添加
    //2、组装QStringList,调用setHorizontalHeaderLabels方法加载进去,列表头不算在数据模型Model里面
    QStringList  tablelHeader;
    for(int i=0;i<m_all_fieldsHeadname.size();i++) {
        tablelHeader << m_all_fieldsHeadname[i];
    }
    qDebug() << __LINE__ << __FUNCTION__<<tablelHeader;
    //tablelHeader<< "选择" <<"序号"<<"编码"<<"名称"<<"品牌"<<"类型"<<"IP地址"<<"更新时间"<<"操作";

注意,两种方式在数据展示上没有差别,但存在一个坑:

当使用代码行添加列表头(tablelHeader)时,当设置勾选项(QCheckBox)的信号和槽函数来获取勾选项(QCheckBox)的位置时,会偏差1行,坑的位置是以下代码row在获取最后一行时,返回的是-1,返回值-1其实是无效的意思。

以下是片段代码
    //关联信号和槽
    QCheckBox *checkBox = new QCheckBox();
    connect(checkBox,SIGNAL(stateChanged(int)),this,SLOT(onCheckBoxStateChanged(int)));


//实现槽函数
void MainWindow::onCheckBoxStateChanged(int state){
    QCheckBox *checkBox =qobject_cast<QCheckBox *>(QObject::sender());

    if(checkBox){
        int row = ui->tableWidget->indexAt(checkBox->mapTo(ui->tableWidget, QPoint(0, 0))).row();
}

我提交的源代码也是使用代码行添加列表头(tablelHeader),但用了另外一个方法来规避此问题,规避方法是row取的是继承tableWidget获取到的row,而不是通过checkBox->mapTo(ui->tableWidget, QPoint(0, 0))反向获取到的行位置(本人未深入研究mapTo,有用此方法解决此问题的兄弟,可以把代码放在评论区),所以不会出现偏差。

代码如下:

void tab_basemsg::renderTable(const QStringList& rowData){
    int row = ui->tableWidget->rowCount();//当前tableWidget显示的行数
    //int rowCount = ui->tableWidget->model()->rowCount();//tableWidget表格中实际的数据行数
    ui->tableWidget->insertRow(row);//在 QTableWidget 中插入新行

    for (int column = 0; column < rowData.size(); ++column) {
        QTableWidgetItem* item = new QTableWidgetItem(rowData.at(column));
        item->setTextAlignment(Qt::AlignCenter);
        ui->tableWidget->setItem(row, column, item);

        if(column == HEAD_BASEMSG_CKBOX){
            //========创建复选框QCheckBox===============
            QCheckBox* checkBox = new QCheckBox();
            QWidget* widget = new QWidget();
            QHBoxLayout* layout = new QHBoxLayout(widget);
            layout->addWidget(checkBox);
            layout->setAlignment(Qt::AlignCenter);
            layout->setContentsMargins(0, 0, 0, 0);
            widget->setLayout(layout);
            if(m_controlstatus==false) checkBox->setEnabled(false); // 设置复选框为不可选中状态
            else checkBox->setEnabled(true); // 设置复选框为可选中状态
            connect(checkBox,&QCheckBox::stateChanged,this,[=](int state){
                //获取当前行的IP
                QString ip = ui->tableWidget->item(row, HEAD_BASEMSG_IP)->text();//可以继承到row
                //qDebug()<< __LINE__ << "state:"<<state;
                qDebug()<< __LINE__ << "row:"<<row << "ip:"<<ip;
                m_iplist.append(ip);
                if (state == Qt::Checked) {
                    for(int i=0;i<HEAD_BASEMSG_NUM;i++){
                        QTableWidgetItem *item = ui->tableWidget->item(row, i);
                        //if(i==0) {item->setText("");}
                        item->setBackground(QBrush(QColor("#308cc6")));
                        item->setForeground(Qt::white);
                    }
                    // 改变操作项图标文件(颜色变化)
                    QWidget *container = ui->tableWidget->cellWidget(row, HEAD_BASEMSG_OPT);
                    if (container) {
                        QLayout *layout = container->layout();
                        if (layout) {
                            if (layout) {
                                QPushButton *editbtn = qobject_cast<QPushButton *>(layout->itemAt(0)->widget());
                                QPushButton *deletebtn = qobject_cast<QPushButton *>(layout->itemAt(1)->widget());
                                editbtn->setIcon(QIcon(":/index/img/edit_ch.png"));
                                deletebtn->setIcon(QIcon(":/index/img/delete_ch.png"));
                            }
                        }
                    }
                }else {
                    for(int i=0;i<HEAD_BASEMSG_NUM;i++){
                        QTableWidgetItem *item = ui->tableWidget->item(row, i);
                        // 设置未选中行的背景颜色为默认颜色
                        item->setBackground(QBrush(Qt::white));
                        item->setForeground(Qt::black);
                    }
                    // 改变操作项图标文件(颜色变化)
                    QWidget *container = ui->tableWidget->cellWidget(row, HEAD_BASEMSG_OPT);
                    if (container) {
                        QLayout *layout = container->layout();
                        if (layout) {
                            if (layout) {
                                QPushButton *editbtn = qobject_cast<QPushButton *>(layout->itemAt(0)->widget());
                                QPushButton *deletebtn = qobject_cast<QPushButton *>(layout->itemAt(1)->widget());
                                editbtn->setIcon(QIcon(":/index/img/edit.png"));
                                deletebtn->setIcon(QIcon(":/index/img/delete.png"));
                            }
                        }
                    }
                }
            });
            ui->tableWidget->setCellWidget(row, column, widget);
        }
        if (column == HEAD_BASEMSG_OPT) {
            //编辑按钮
            QPushButton* edit = new QPushButton();
            edit->setIcon(QIcon(":/index/img/edit.png"));
            edit->setIconSize(QSize(24, 24));
            edit->setStyleSheet("QPushButton { border: none; }");
            edit->setCursor(Qt::PointingHandCursor);
            //删除按钮
            QPushButton* deleteButton = new QPushButton();
            deleteButton->setIcon(QIcon(":/index/img/delete.png"));
            deleteButton->setIconSize(QSize(24, 24));
            deleteButton->setStyleSheet("background-color:rgba(0,0,0,0);border:none;");
            deleteButton->setCursor(Qt::PointingHandCursor);
            //按钮信号监听
            connect(edit,SIGNAL(clicked()),this,SLOT(editBasemsg()));
            connect(deleteButton,SIGNAL(clicked()),this,SLOT(delBasemsg()));

            QWidget* widget = new QWidget();
            QHBoxLayout* layout = new QHBoxLayout(widget);
            layout->addWidget(edit);
            layout->addWidget(deleteButton);
            layout->setAlignment(Qt::AlignCenter);
            layout->setContentsMargins(0, 0, 0, 0);
            widget->setLayout(layout);
            ui->tableWidget->setCellWidget(row, column, widget);
        }
    }
}

(2)QTableView中创建QCheckBox

QCheckBox需要通过widget加载到QTableView中,代码如下:

            //创建勾选项
            QCheckBox* checkBox = new QCheckBox();
            //创建窗口视图
            QWidget* widget = new QWidget();
            //创建布局
            QHBoxLayout* layout = new QHBoxLayout(widget);
            //把勾选项加载到布局中
            layout->addWidget(checkBox);
            layout->setAlignment(Qt::AlignCenter);
            layout->setContentsMargins(0, 0, 0, 0);
            //把布局设置到窗口视图中
            widget->setLayout(layout);
            //把窗口视图中展示到tableWidget的指定位置
            ui->tableWidget->setCellWidget(row, column, widget);

        QCheckBox勾选项关联的信号和槽的代码参见【(1)创建QTableView列表头】分享的renderTable()函数源代码。

(3)QTableView中创建QPushButton

        QPushButton与QCheckBox一样,也是需要widget加载到QTableView,不过可以设置QPushButton的尺寸、背景颜色等友好展示的布局,源码如下所示:

//编辑按钮
            QPushButton* edit = new QPushButton();
            edit->setIcon(QIcon(":/index/img/edit.png"));
            edit->setIconSize(QSize(24, 24));
            edit->setStyleSheet("QPushButton { border: none; }");
            edit->setCursor(Qt::PointingHandCursor);
            //删除按钮
            QPushButton* deleteButton = new QPushButton();
            deleteButton->setIcon(QIcon(":/index/img/delete.png"));
            deleteButton->setIconSize(QSize(24, 24));
            deleteButton->setStyleSheet("background-color:rgba(0,0,0,0);border:none;");
            deleteButton->setCursor(Qt::PointingHandCursor);
            //按钮信号监听
            connect(edit,SIGNAL(clicked()),this,SLOT(editBasemsg()));
            connect(deleteButton,SIGNAL(clicked()),this,SLOT(delBasemsg()));

            QWidget* widget = new QWidget();
            QHBoxLayout* layout = new QHBoxLayout(widget);
            layout->addWidget(edit);
            layout->addWidget(deleteButton);
            layout->setAlignment(Qt::AlignCenter);
            layout->setContentsMargins(0, 0, 0, 0);
            widget->setLayout(layout);
            ui->tableWidget->setCellWidget(row, column, widget);

(4)QTableView创建右键菜单

①在头文件中添加右键菜单绑定的槽函数,源码如下:

//tab_basemsg.h
private slots:
    //处理右键菜单请求
    void tableWidget_MenuRequested(const QPoint &pos);

②设置右键功能及关联信号和槽,并实现槽函数(在槽函数中增加具体的右键菜单名称),源码如下:

//tab_basemsg.cpp
//设置右键菜单功能
ui->tableWidget->setContextMenuPolicy(Qt::CustomContextMenu);
//绑定右键功能槽函数
connect(ui->tableWidget, &QTableWidget::customContextMenuRequested, this, &tab_basemsg::tableWidget_MenuRequested);

//槽函数实现
void tab_basemsg::tableWidget_MenuRequested(const QPoint &pos) {
    QModelIndex index = ui->tableWidget->indexAt(pos);//获取当前行
    if (!index.isValid()) return;

    QMenu menu(this);
    QAction *DiplaymsgAction = menu.addAction(tr("查看详情"));
    connect(DiplaymsgAction,&QAction::triggered,[=](){
        //获取选择的单元格
        QList<QTableWidgetItem *> selected_cells = ui->tableWidget->selectedItems();
        if(!selected_cells.isEmpty()){
            QTableWidgetItem *codeCell = ui->tableWidget->item(selected_cells.first()->row(),HEAD_BASEMSG_CODE);
            if(codeCell!=nullptr){
                QString code = codeCell->text();
                stBasemsg basemsg=m_basemsgmap[code];
                basemsgDialg->setModal(false);
                basemsgDialg->setWindowTitle("保存");
                //basemsgDialg->setFixedSize(500,400);
                basemsgDialg->open();
                basemsgDialg->init(1,basemsg);
                basemsgDialg->exec();
            }
        }
    });
    QAction *NetpingAction = menu.addAction(tr("Ping此计算机"));
    connect(NetpingAction,&QAction::triggered,[=](){
        //获取选择的单元格
        QList<QTableWidgetItem *> selected_cells = ui->tableWidget->selectedItems();
        if(!selected_cells.isEmpty()){
            QTableWidgetItem *codeCell = ui->tableWidget->item(selected_cells.first()->row(),HEAD_BASEMSG_CODE);
            if(codeCell!=nullptr){
                QString code = codeCell->text();
                stBasemsg basemsg=m_basemsgmap[code];
                QString ip=basemsg.Ip;
                qDebug() << __LINE__ << ip;
                pingdlg->setIp(ip);
                pingdlg->setModal(false);
                pingdlg->setWindowTitle("PING测试");
                pingdlg->setFixedSize(500,400);
                pingdlg->open();
                pingdlg->init();
                pingdlg->exec();
            }
        }
    });

    menu.exec(QCursor::pos());
    //menu.exec(ui->tableWidget->mapToGlobal(pos));
}

篇尾

        因为多个勾选项很多情况下涉及多项数据的处理,有些处理是要异步才不会导致主界面卡顿,下一篇用多线程+ping+全局变量+结果展示技术点(【QT常用技术讲解】多线程处理+全局变量处理异步事件并获取多个线程返回的结果),来详细讲解【多线程解决QTableView多勾选项右键菜单功能卡顿问题】。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值