QT自学记录(2)——信号与槽

一. 信号和槽的定义和性质

  信号(Signal),顾名思义,是特定情况下被触发的事件。譬如老师在下课时会肚子饿,那么肚子饿就是一种信号;而PushButton会被点击,点击(clicked())也是一种信号;ComboBox选择的列表项发生变化时,会触发CurrentIndexChanged()的信号。

  与之对应,一个对象发出信号,那么另一个对象(也可以是发出信号的对象本身)会执行相应的动作,而这些相应的动作所组成的函数,就叫槽(Slot)。当信号被发射的时候,就可以触发对应的槽函数。譬如老师在下课时发出(emit)肚子饿的信号,可以触发老师肚子叫(grumble())的槽函数;此时也有可能有学生发现老师饿了,从而请老师吃饭,触发学生的请客(treat())槽函数。

  从上面的说明我们不难看出信号和槽的一些性质:

  1. 一个信号可以与多个槽对应,也可以不对应任何槽函数;
  2. 信号可以连接槽,也可以连接新的信号;
  3. 槽函数的执行者可以为信号发出者本身。

  此外,信号和槽还具有如下的特性:

  1. 信号和槽函数均可以带参数,因而可以发生重载(重载可能发生的问题将会在后面提到)
  2. 信号只需使用signal关键字声明,无需实现,但槽函数必须在后续实现;
  3. 信号和槽函数均是无返回值的void函数;
  4. 信号和槽函数含有的参数数量可以不同,但是槽函数的参数必须不多于信号的参数;
  5. 信号和槽函数的参数必须一一对应。

二. 信号的发送、信号和槽的连接

  信号的触发可以由对可视化的PushButtonComboBox等对象的操作发送,也可以由QT自带的emit关键字触发。由可视化对象的触发的信号:包括clicked()CurrentIndexChanged()等,而emit关键字则可触发任何信号。

  信号和槽可由connect(sender,signal,receiver,slot)函数进行连接。connect函数最传统的写法是如下的(下面以PushButton为例):

class MyButton : public QWidget
{
    Q_OBJECT
public:
    explicit MyButton(QWidget *parent = nullptr);
signals:
void sigClicked(); void sigClicked(bool check); }; connect(m_pBtn,SIGNAL(sigClicked()),this,SLOT(onClicked())); connect(m_pBtn,SIGNAL(sigClicked(bool)),this,SLOT(onClicked(bool)));

 

  这种写法最大的好处是能够在含有信号重载的时候让编译器直观地寻找到所匹配的信号函数和槽函数,但是容易在编写程序时漏掉括号,写起来未免会觉得有些麻烦。。。察觉到此写法的复杂性,QT在5.0及其之后的版本推出了另一种写法:

connect(m_pBtn,&MyButton::sigClicked,this,&Widget::onClicked);

  看到这里笔者第一反应当然是轻松了很多,于是开心地将这行代码粘贴到了程序中,然后开心地获得了如下的编译错误:

error: no matching member function for call to 'connect' connect(m_pBtn,&MyButton::sigClicked,this,&Widget::onClicked);

  这是因为编译器在回去寻找sigClicked函数时,会找到两个(甚至是更多)信号函数,而这会使得函数不知道该匹配哪个,从而导致conflict。而这个bug的解决方案也相对简单:使用函数指针,例如下面的写法(当然也可在外部定义函数指针后再connect):

 

connect(m_pBtn, static_cast<void (MyButton::*)(bool)>(&MyButton::sigClicked), this, &Widget::onClicked);

 

  函数指针的使用也相对较为简单,但是构建函数指针的码量较大,且当信号函数/槽函数发生多次重载时,需要定义多个函数指针,也会导致检查较为困难。因此笔者本人较为崇尚第一种写法。

  同时,connect也可以用于连接信号:

connect(btn, SIGNAL(clicked()), this, SIGNAL(todosth()))

  (参考资料:https://blog.csdn.net/luoyayun361/article/details/80768567

 

 

posted @ 2021-08-13 16:03  MingQian1391  阅读(132)  评论(0)    收藏  举报