QT的信号和槽机制

信号和槽是QT编程的重要部分

它提供了对象间的通信机制。迅速,类型安全,健壮,完全面向对象的用C++来实现的机制。

我们在用回调函数机制把某段响应代码和一个按钮的动作相关联的时候,通常把响应代码写成函数,然后把这个函数的地址指针传给按钮,当那个按钮被单击时,这个函数就会被执行。对于这种方式,以前的开发包不能够确保回调函数被执行时所传递进来的函数参数就是正确的类型,因此容易造成进程崩溃。另外一个问题是,回调这种方式紧紧地绑定了图形用户接口的功能元素,因而很难把开发进行独立的分类。

Qt的信号和槽机制是不同的,Qt的窗口在事件发生后会激发信号。例如,一个按钮被单击时会激发一个clicked信号,我们通过建立一个函数(称作一个槽),然后调用connect()函数把这个槽和一个信号连接起来,这样就完成了一个事件和响应代码的连接。信号和槽机制并不要求类之间互相知道细节,这样就可以相对容易的开发出代码可高重用的类。信号和槽机制是类型安全的,它以警告的方式报告类型错误,而不会使系统崩溃。例如,如果一个退出按钮的clicked()信号被连接到了一个应用的退出函数——槽quit(),那么一个用户单击退出键将使应用程序中止运行。上述的连接过程用代码写出来就是这样:

connect(button,SIGNAL(clicked()),qApp,SLOT(quit()))//connect()函数把槽和信号连接在一起
    //SIGNAL()信号00
    //SLOT()槽

我们可以在Qt程序执行的过程增加或减少信号和槽的连接,信号和槽的实现拓展了C++的语法,完全利用了C++面向对象的特征。信号和槽可以被重载或重写,它门可以被定义为类的公有,私有或保护成员。

信号:当对象的内部状态发生改变,信号(signal)就会被发送。只有定义了一个信号的类和它的子类才能发送这个信号

如果两个不同的类对同一个信号感兴趣,可以将这个信号和这个两个对象连接起来。当信号被发送后,它所连接的槽会被立刻执行,就像一个普通函数被调用一样。信号和槽机制完全不依赖任何一种图形用户界面的事件回路。当所有的槽都返回后emit也将返回。

如果几个槽被连接到一个信号,当信号被发送后,它所连接的槽会按任意顺序一个接着一个执行 ( Qt5后,在信号发射后,槽函数会按照链接顺序执行)

槽:槽(Slot)就是对信号响应的函数。槽就是一个函数,与一般的C++函数是一样的,可以定义在类的任何部分(public、private 或 protected),可以具有任何参数,也可以被直接调用。槽函数与一般的函数不同的是:槽函数可以与一个信号关联,当信号被发射时,关联的槽函数被自动执行。

信号与槽关联是用 QObject::connect() 函数实现的,其基本格式是:

QObject::connect(sender, SIGNAL(signal()), receiver, SLOT(slot()));

connect() 是 QObject 类的一个静态函数,而 QObject 是所有 Qt 类的基类,在实际调用时可以忽略前面的限定符,所以可以直接写为:

connect(sender,SIGNAL(signal),receiver,SLOT(slot))//connect()函数把槽和信号连接在一起
    //sender,receiver是QObject对象指针,signal,slot是不带参数的函数原型
    //SIGNAL(),SLOT()的作用是把它门转化成字符串
    //SIGNAL(signal)信号
    //SLOT(slot)槽

其中,sender 是发射信号的对象的名称,signal() 是信号名称。信号可以看做是特殊的函数,需要带括号,有参数时还需要指明参数。receiver 是接收信号的对象名称,slot() 是槽函数的名称,需要带括号,有参数时还需要指明参数。

SIGNAL 和 SLOT 是 Qt 的宏,用于指明信号和槽,并将它们的参数转换为相应的字符串。例如,在 samp2_1(前面章节中的项目)的 ui_widget.h 文件中,在 setupUi() 函数中有如下的语句:

QObject::connect(btnClose, SIGNAL(clicked()), Widget, SLOT(close()));

其作用就是将 btnClose 按钮的 clicked() 信号与窗体(Widget)的槽函数 close() 相关联,这样,当单击 btnClose 按钮(就是界面上的“Close”按钮)时,就会执行 Widget 的 close() 槽函数。

关于信号与槽的使用,有以下一些规则需要注意:

  • 一个信号可以连接多个槽,例如:

    connect(spinNum, SIGNAL(valueChanged(int)), this, SLOT(addFun(int));
    connect(spinNum, SIGNAL(valueChanged(int)), this, SLOT(updateStatus(int));
    

    这是当一个对象 spinNum 的数值发生变化时,所在窗体有两个槽进行响应,一个 addFun()用于计算,一个 updateStatus() 用于更新状态。

    当一个信号与多个槽函数关联时,槽函数按照建立连接时的顺序依次执行。

    当信号和槽函数带有参数时,在 connect()函数里,要写明参数的类型,但可以不写参数名称。

  • 多个信号可以连接同一个槽,例如在 samp2_2(前面章节中的项目)中,让三个选择颜色的 RadioButton的clicked() 信号关联到相同的一个自定义槽函数 setTextFontColor()。

    connect(ui->rBtnBlue,SIGNAL(clicked()),this,SLOT(setTextFontColor()));
    connect(ui->rBtnRed,SIGNAL(clicked()),this,SLOT(setTextFontColor()));
    connect(ui->rBtnBlack,SIGNAL(clicked()),this,SLOT(setTextFontColor()));
    

    这样,当任何一个 RadioButton 被单击时,都会执行 setTextFontColor() 函数。

  • 一个信号可以连接另外一个信号,例如:

    connect(spinNum, SIGNAL(valueChanged(int)), this, SIGNAL (refreshInfo(int));
    

    这样,当一个信号发射时,也会发射另外一个信号,实现某些特殊的功能。

  • 严格的情况下,信号与槽的参数个数和类型需要一致,至少信号的参数不能少于槽的参数。如果不匹配,会出现编译错误或运行错误。

  • 在使用信号与槽的类中,必须在类的定义中加入宏 Q_OBJECT。

  • 当一个信号被发射时,与其关联的槽函数通常被立即执行,就像正常调用一个函数一样。只有当信号关联的所有槽函数执行完毕后,才会执行发射信号处后面的代码。

信号与槽机制是 Qt GUI 编程的基础,使用信号与槽机制可以比较容易地将信号与响应代码关联起来。

posted @ 2021-03-27 21:18  空忏辰/landabai  阅读(309)  评论(0)    收藏  举报