论文部分内容阅读
信号槽作为Qt的核心机制,区别于众多GUI开发语言。本文深入剖析Qt信号槽机制在开发中的应用问题。
信号和槽特点:用户交互方式是所有GUI(Graphical user interface)应用程序关心的问题。通过将某种用户事件(比如按下鼠标)与程序事件(比如退出程序)联系起来,使用户能够在图形界面中只使用鼠标来控制程序。Qt提供信号和槽概念,这是一种安全可靠的方法,它允许回调,并支持对象之间在彼此不知道对方信息的情况下,进行合作,这使Qt非常合适于真正的组件编程。
其他工具包是利用回调函数来进行用户交互的,回调函数只能是全局函数,或者是静态函数,因为这个函数只是在类中使用,所以为了维护类的完整性,我们用类的静态成员函数来做回调函数。虽然回调函数能够实现用户之间的交互。但是,回调函数非常复杂,容易混淆,又难以理解。因此,Qt使用另一种方法来完成这一工作。这种方法依赖于Qt特有的两个功能:信号和槽。使用这种新方法是非常简单的,只需要编写一行代码就能够将用户事件和程序事件连接起来。
这种将用户事件连接到程序事件的方法要比回调函数更加容易使用的两个重要原因是:1.槽和信号是你调用Qt库中的函数。2. 信号和槽不使用其他工具包。
信号和槽用于对象间的通信,该机制是Qt的一个中心特征,并且最能体现Qt与其他工具包之间有什么不同。在图形用户界面编程中,我们经常希望一个窗口部件的某个变化被告知给另外一个窗口部件或者一个线程的状态或数据告知另外一个线程。简单的说,我们希望任何一类的对象可以和其他对象进行通信。例如:我们正在接收一个网络包,当我们遇到一个波形数据的时候,我们也许希望告知绘图窗口,我们用绘图窗口来绘制波形数据。
比较老的工具包使用一种被称做回调的通信方式来实现同一目的。回调有两个主要缺点:1.它们不是类型安全的。我们从来都不能确定处理函数是否使用了正确的参数来调用回调。2.回调和处理函数是紧耦合的,因为处理函数必须要知道调用哪个回调。
槽函数特点:当信号被发出时,会调用与之相连接的槽。槽是普通的C++函数,可以用普通的方式来调用。它唯一特殊的地方在于可以与信号相连接。槽的参数不能有默认值。同样,信号的参数也不能有默认值。在槽的参数中尽量不使用自定义的数据类型,因为这样将会使通用性降低。
既然槽和普通的成员函数差不多,它们和普通成员函数一样有访问限制,根据槽的访问,限制谁可以与它们相连接,并分为以下三种情况。
public slot:任何信号都可以与之相连接。这在窗口部件编程中非常有用,用于创建一些对彼此一无所知的对象,只有通过信号和槽来交换信息。public slot就像是标准的铁路一样。
protected slot:只有该类及其子类所派生的对象的信号才可以与之相连接。这类槽的目的通常是为了类的完善,而不是类与外界的接口。
private slot:只有该类自己的信号才可以与之相连接。
信号和槽的使用:信号和槽是相当高效的。当然,它们与“实时”的回调函数相比,在增加了灵活性的同时也损失了一些速度,正所谓有利必有弊,但是这种速度的损失相当微不足道。因此,信号/槽机制具有简便性和灵活性的特性,使用信号和槽是用户交互的必然选择。槽的声明也是在头文件中进行的。
当某个信号所对应的客户或其所有者的内部状态发生改变时,信号被一个对象发射。只有定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,与其相关联的槽将被立刻执行,就象调用一个正常的函数一样。信号-槽机制完全独立于任何GUI事件循环。只有当所有的槽返回以后发射函数(emit)才返回。如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪个后执行。
一个列表框可以发出highlighted()和activated()的信号,大多数对象也许只对activated()的信号感兴趣,但也许有些对象需要知道该列表框中的哪一项被选中了。如果有两个不同的对象对一个信号感兴趣,只要将该信号连接到这两个对象的槽上就可以了。
信号:使用emit发送信号,就好象是你编写的程序直接调用每一个槽方法一样。也就是说,直到槽方法返回,你编写的程序才能继续执行。因此,通常应当保持在槽方法内部的处理过程中尽可能的简单,这样才不会因此中止信号的发送。发送信号的可能是用户接口过程,操作过程表现得比较慢或者缓慢。
注意槽和信号在連接语句中的参数是否匹配。在线程间如果需要使用信号槽交互,需要用到connect()第五个参数(Qt::ConnectionType?type?= Qt::QueuedConnection)此时槽函数运行于信号接收线程。此时信号槽如果需要传送参数, 参数必须被Qt元对象系统定义参数,如果使用自定义参数类型的,必须在信号槽连接前把参数通过qRegisterMetaType()注册到元对象系统,否则则会报如下错:
QObject:connect: Cannot queue arguments of type 'MyType'
总结:信号与槽机制作为Qt的核心机制,在Qt程序设计中大量运用,合理正确的使用信号与槽机制能使程序设计模块化程度更高。
信号和槽特点:用户交互方式是所有GUI(Graphical user interface)应用程序关心的问题。通过将某种用户事件(比如按下鼠标)与程序事件(比如退出程序)联系起来,使用户能够在图形界面中只使用鼠标来控制程序。Qt提供信号和槽概念,这是一种安全可靠的方法,它允许回调,并支持对象之间在彼此不知道对方信息的情况下,进行合作,这使Qt非常合适于真正的组件编程。
其他工具包是利用回调函数来进行用户交互的,回调函数只能是全局函数,或者是静态函数,因为这个函数只是在类中使用,所以为了维护类的完整性,我们用类的静态成员函数来做回调函数。虽然回调函数能够实现用户之间的交互。但是,回调函数非常复杂,容易混淆,又难以理解。因此,Qt使用另一种方法来完成这一工作。这种方法依赖于Qt特有的两个功能:信号和槽。使用这种新方法是非常简单的,只需要编写一行代码就能够将用户事件和程序事件连接起来。
这种将用户事件连接到程序事件的方法要比回调函数更加容易使用的两个重要原因是:1.槽和信号是你调用Qt库中的函数。2. 信号和槽不使用其他工具包。
信号和槽用于对象间的通信,该机制是Qt的一个中心特征,并且最能体现Qt与其他工具包之间有什么不同。在图形用户界面编程中,我们经常希望一个窗口部件的某个变化被告知给另外一个窗口部件或者一个线程的状态或数据告知另外一个线程。简单的说,我们希望任何一类的对象可以和其他对象进行通信。例如:我们正在接收一个网络包,当我们遇到一个波形数据的时候,我们也许希望告知绘图窗口,我们用绘图窗口来绘制波形数据。
比较老的工具包使用一种被称做回调的通信方式来实现同一目的。回调有两个主要缺点:1.它们不是类型安全的。我们从来都不能确定处理函数是否使用了正确的参数来调用回调。2.回调和处理函数是紧耦合的,因为处理函数必须要知道调用哪个回调。
槽函数特点:当信号被发出时,会调用与之相连接的槽。槽是普通的C++函数,可以用普通的方式来调用。它唯一特殊的地方在于可以与信号相连接。槽的参数不能有默认值。同样,信号的参数也不能有默认值。在槽的参数中尽量不使用自定义的数据类型,因为这样将会使通用性降低。
既然槽和普通的成员函数差不多,它们和普通成员函数一样有访问限制,根据槽的访问,限制谁可以与它们相连接,并分为以下三种情况。
public slot:任何信号都可以与之相连接。这在窗口部件编程中非常有用,用于创建一些对彼此一无所知的对象,只有通过信号和槽来交换信息。public slot就像是标准的铁路一样。
protected slot:只有该类及其子类所派生的对象的信号才可以与之相连接。这类槽的目的通常是为了类的完善,而不是类与外界的接口。
private slot:只有该类自己的信号才可以与之相连接。
信号和槽的使用:信号和槽是相当高效的。当然,它们与“实时”的回调函数相比,在增加了灵活性的同时也损失了一些速度,正所谓有利必有弊,但是这种速度的损失相当微不足道。因此,信号/槽机制具有简便性和灵活性的特性,使用信号和槽是用户交互的必然选择。槽的声明也是在头文件中进行的。
当某个信号所对应的客户或其所有者的内部状态发生改变时,信号被一个对象发射。只有定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,与其相关联的槽将被立刻执行,就象调用一个正常的函数一样。信号-槽机制完全独立于任何GUI事件循环。只有当所有的槽返回以后发射函数(emit)才返回。如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪个后执行。
一个列表框可以发出highlighted()和activated()的信号,大多数对象也许只对activated()的信号感兴趣,但也许有些对象需要知道该列表框中的哪一项被选中了。如果有两个不同的对象对一个信号感兴趣,只要将该信号连接到这两个对象的槽上就可以了。
信号:使用emit发送信号,就好象是你编写的程序直接调用每一个槽方法一样。也就是说,直到槽方法返回,你编写的程序才能继续执行。因此,通常应当保持在槽方法内部的处理过程中尽可能的简单,这样才不会因此中止信号的发送。发送信号的可能是用户接口过程,操作过程表现得比较慢或者缓慢。
注意槽和信号在連接语句中的参数是否匹配。在线程间如果需要使用信号槽交互,需要用到connect()第五个参数(Qt::ConnectionType?type?= Qt::QueuedConnection)此时槽函数运行于信号接收线程。此时信号槽如果需要传送参数, 参数必须被Qt元对象系统定义参数,如果使用自定义参数类型的,必须在信号槽连接前把参数通过qRegisterMetaType()注册到元对象系统,否则则会报如下错:
QObject:connect: Cannot queue arguments of type 'MyType'
总结:信号与槽机制作为Qt的核心机制,在Qt程序设计中大量运用,合理正确的使用信号与槽机制能使程序设计模块化程度更高。