第3章 信号和槽
3.1 基本概念
在第2章中,我们已经接触了信号和槽,当用户触发了一个菜单动作时,就产生了一个菜单触发信号,主窗口用相应的操作响应信号,执行相应的操作,该响应操作即为槽。在Qt中,Qt的部件已经预定义了很多信号和槽,信号如triggered()等,槽包括close()、hide()、show()等,用户也可以在类中增加新的信号和槽,以便实现特定的功能。
Qt中还有一种响应机制: 事件。Qt中的事件主要来自底层的窗口系统,如鼠标、键盘、定时器、网络等,对事件的响应一般采用重载类的成员函数来实现,例如前面我们实现的mouseMoveEvent、TimerEvent等。从实现上,事件比信号和槽要更底层一些,例如单击鼠标首先产生mousePressEvent,再在部件中产生triggered信号。
信号和槽遵循C++的基本语法,在定义信号和槽时,只需添加关键字slots和signals即可,例如:
… public slots: void setValue(int value); signals: void valueChanged(int newValue); …
要实现信号和槽的关联,用connect操作实现,例如:
connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
即把触发“关于”菜单项的信号传递给窗口的“关于”操作,实现对菜单的响应。
信号和槽是Qt对象的重要特征,使用的信号和槽必须是QObject的子类,否则无法使用信号和槽来建立关联。信号和槽是类型安全的,只要信号的参数在顺序上是大于槽的参数,即可建立匹配,在响应的时候,系统自动匹配满足槽的参数,放弃多余的参数。图3-1给出了信号和槽关联的示意,在Qt中,信号和槽也是松耦合的,可以各自在类中定义和实现,彼此在连接时进行参数匹配之外,没有任何相关性。一个信号可以触发多个槽,多个信号也可以连接至一个槽。需要注意的是,在槽中发射信号不要产生死循环。

图3-1 信号和槽关联示意图
先不着急学习怎么用C++编写信号和槽的代码,既然信号和槽主要用于窗口部件间的联系,那么我们还是从Qt Designer入手,用实例理解信号和槽的实现。