【QT常用技术讲解】信号和槽

前言

        本文内容结合本人引用的代码,在QT项目的开发框架提供下载的源代码中可以找到。另外,本人风格倾向于用最常用(最高效)的方式去实现功能,而非学术性的全面讲解。

概述

        信号和槽(函数),可以理解为收到信号后,就执行槽函数。风格上有些类似于多线程编程时,引用线程函数一样。

功能讲解

        信号和槽常见的场景有以下几种:

(1)同一个cpp里面,某个控件触发点击事件功能;

(2)A.cpp调用对话框,等待对话框返回数值给A.cpp;

(3)A.cpp调用对话框,A.cpp使用B.cpp的槽函数来等待对话框的返回值;

同一个cpp里面,某个控件触发点击事件功能

这是最常见的,单击按钮之后,触发的按钮单击函数,如下操作之后,QT自动帮忙connect了,此时你在手动写一遍connect函数也不影响。

//添加功能
void tab_basemsg::on_basemsgadd_pushbutton_clicked()
{
    qDebug() << __LINE__ << __FUNCTION__;
    //int rowCount = ui->usbchangetable->rowCount();
    stBasemsg st_basemsg=stBasemsg();
    qDebug() << __LINE__ << "on_usbchangeButton_clicked";
    basemsgDialg->setModal(false);
    basemsgDialg->setWindowTitle("添加");
    //basemsgDialg->setFixedSize(600,560);
    basemsgDialg->open();
    basemsgDialg->init(0,st_basemsg);
    basemsgDialg->exec();
}

A.cpp调用对话框,等待对话框返回数值给A.cpp

等待有两种方式,一种是在connect中直接用参数接入,一种是在connect中用槽函数来接入

(1)在connect中直接用参数接入的方式(以上面添加功能中调用basemsgDialg对话框为例):

首先在basemsgDialg的头文件中声明信号:

signals:
    void refreshbasemsg(int flag,const stBasemsg& basemsg);

然后在basemsgDialg的保存按钮中,处理完数据之后,使用emit refreshbasemsg(m_flag,addmsg);把信号发送出去,如下

void basemsgaddDialog::on_pushButton_save_clicked()
{
    bool bfind=true;
    QString code=ui->lineEdit_code->text();
    QString name=ui->lineEdit_name->text();
    QString brand=ui->lineEdit_brand->text();
    QString type_name = ui->comboBox->currentText();
    if(code==""||name==""||brand==""){
        QMessageBox::information(this, "提示框", "输入框不能为空");
        bfind=false;
    }else if(m_flag==0&&m_basemsgmap.contains(code)){
        QMessageBox::information(this, "提示框", code+"已经存在,不能重复输入");
        bfind=false;
    }
    if(bfind){
        stBasemsg addmsg;
        addmsg.code=code;
        addmsg.name=name;
        addmsg.brand=brand;
        addmsg.type_name=type_name;
        addmsg.updatetime=comfun.getcurtime();
        //把数据回写回去
        emit refreshbasemsg(m_flag,addmsg);//发送信号带数据给回菜单
        close();//关闭当前窗口
    }
}

此时在tab_basemsg中构造函数中的connect,绑定信号basemsgaddDialog::refreshbasemsg,即可接收到信号的返回值,如下代码使用的是直接获取参数的方式

tab_basemsg::tab_basemsg(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::tab_basemsg)
{
    ui->setupUi(this);
    //tab_basemsg::resize(800,500);
    //ui->tableWidget->resize(WD_BASE_WIDTH, WD_BASE_HEIGHT);
    init();
    //读取json数据,显示表格信息
    ShowTableContent();

    basemsgDialg = new basemsgaddDialog(this);
    connect(basemsgDialg,&basemsgaddDialog::refreshbasemsg,this,[=](int flag,const stBasemsg& basemsg){
        qDebug()<< __LINE__ << "refreshbasemsg";
        if(flag==0){
            comfun.insertjsondata(basemsg,BASEMSG_JSONPATH);
        }else{
            comfun.updatejsondata(basemsg,BASEMSG_JSONPATH);
        }
        ShowTableContent();//重新更新表格数据
    });

}

(2)在connect中调用处理函数方式来处理

此时,(1)tab_basemsg中的connect可以改造为:

connect(basemsgDialg,&basemsgaddDialog::refreshbasemsg,this,tab_basemsg::dealdata);

补上dealdata()的声明和实现,如下代码所示:

//tab_basemsg.h中声明:
void dealdata(int flag,const stBasemsg& basemsg);

//tab_basemsg.cpp中实现
void tab_basemsg::dealdata(int flag,const stBasemsg& basemsg){
    if(flag==0){
            comfun.insertjsondata(basemsg,BASEMSG_JSONPATH);
        }else{
            comfun.updatejsondata(basemsg,BASEMSG_JSONPATH);
        }
        ShowTableContent();//重新更新表格数据
}

因为实现只有几行代码,本人就选择最快的方式:使用connect传参数。

A.cpp调用对话框,A.cpp使用B.cpp的槽函数来等待对话框的返回值

用我提供的开发框架中的字段管理功能为例:点击【字段管理】图标,弹出字段选择对话框,勾选字段提交成功后,基础信息界面同步刷新最后勾选的字段。

第一步:在bar_fieldsmgt中声明信号,并在点击【确认】按钮后发送信号:

//bar_Fieldsmgt.h
public:
    explicit bar_Fieldsmgt(QWidget *parent = nullptr);
    ~bar_Fieldsmgt();
signals:
    void refreshfieldsmgt(QString fieldsset);


//bar_Fieldsmgt.cpp
void bar_Fieldsmgt::on_pushButton_save_clicked()
{
    QString confstr="";
    for (auto child : this->findChildren<QCheckBox*>()) {
        //qDebug()<< child->text() << " is checked:"<< child->isChecked();
        confstr+=(child->isChecked())?"1":"0";
        confstr+="|";
    }
    confstr.chop(1); // 去掉最后一个字符
    qDebug()<< __LINE__ << confstr;
    AppConfig::Get().writeIni(QString(BASE_FILE_NAME), QString("MENU_CONF"),QString("field"), confstr);
    //把数据回写回去
    emit refreshfieldsmgt(confstr);//发送信号带数据给回菜单
    close();//关闭当前窗口
}

因为【字段管理】图标在主界面,所有在主界面的构造函数中编写connect接收信号:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
......
//用基础表的刷新表格页面函数响应工具栏的【列表管理】信号==>调用A页面,以B页面的函数响应信号
    connect(fieldsmgt,&bar_Fieldsmgt::refreshfieldsmgt,basemsg,tab_basemsg::reShowTableContent);
}

注意上面connect后面两个参数是调用tab_basemsg类的reShowTableContent()函数对表格重新展示了,这样使用的原因是:tab_basemsg跟主界面是分开的,不同的类,主界面拿到返回信息无法直接刷新tab_basemsg界面的表格,不如直接调用tab_basemsg界面的处理函数去刷新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值