前言
本文内容结合本人引用的代码,在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界面的处理函数去刷新。