QT开发(十三)——QT信号与槽机制

QT开发(十三)——QT信号与槽机制

一、QT消息模型

QT封装了具体操作系统的消息机制,遵循经典的GUI消息驱动事件模型。

QT定义了与操作系统消息相关的自己的概念,即信号与槽。

信号signal是由操作系统产生的消息。

槽slot是程序中的消息处理函数。

connect将系统消息绑定到消息处理函数。

信号到槽的连接必须发生在两个QT对象间。

bool QObject::connect ( const QObject * sender, //发生对象

const char * signal, //消息名

const QObject * receiver, //接收对象

const char *method, //接收对象的成员函数

Qt::ConnectionType type = Qt::AutoConnection )

在QT中消息使用字符串进行描述,connect函数在消息名和处理函数之间建立映射。

QT中的关键字

SIGNAL用于指定消息名

SLOT用于指定消息处理函数名

Q_OBJECT所以自定义槽的类必须在类声明的开始处加上Q_OBJECT

slots用于在类中声明消息处理函数

二、信号与槽机制

信号和槽机制是QT的核心机制,是一种高级接口,应用于QT对象之间的通信,是QT的核心特性,也是QT区别于其它工具包的重要地方。信号和槽是QT自行定义的一种通信机制,独立于标准的C/C++语言,要正确的处理信号和槽,必须借助一个称为moc(Meta Object Compiler)的QT工具,MOC工具是一个C++预处理程序,为高层次的事件处理自动生成所需要的附加代码。

在QT中信号和槽取代了传统GUI框架中的回调函数,信号和槽能携带任意数量和任意类型的参数,是类型完全安全的。所有从QObject或其子类(如Qwidget)派生的类都能够包含信号和槽。当对象改变其状态时,信号就由对象发射(emit)出去,但对象不知道另一端是谁在接收信号。槽用于接收信号,但槽是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接,而且对象并不了解具体的通信机制。

1、信号

当某个信号对其客户或所有者发生的内部状态发生改变,信号被一个对象发射。只有定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。信号-槽机制完全独立于任何GUI事件循环。只有当所有的槽返回以后发射函数(emit)才返回。 如果存在多个槽与某个信号相关联,当这个信号被发射时,这些槽将会一个接一个地执行,但执行的顺序将会是随机的,不能人为地指定哪个先执行、哪个后执行。

信号的声明是在头文件中进行的,QT的signals关键字指出进入了信号声明区,随后即可声明自己的信号。

signals:

void overflow();

signals是QT的关键字,而非C/C++的。信号可以重载,但信号却没有函数体定义,并且信号的返回类型都是void,不要指望能从信号返回什么有用信息。

信号由moc自动产生,不应该在.cpp文件中实现。

2、

槽是普通的C++成员函数,可以被正常调用,唯一的特殊性就是很多信号可以与其相关联。当与其关联的信号被发射时,信号关联的槽就会被调用。槽可以有参数,但槽的参数不能有缺省值。

槽是普通的成员函数,也有访问权限。槽的访问权限决定了谁能够与其相关联。同普通的C++成员函数一样,槽函数也分为三种类型,即public slots、private slots和protected slots。

public slots:使用publicslots声明的槽表示任何对象都可将信号与之相连接。在组件编程中,可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。

protected slots:使用protected slots声明的槽表示当前类及其子类可以将信号与之相连接。适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。

private slots:使用private slots声明的槽表示只有类自己可以将信号与之相连接,适用于联系非常紧密的类。

槽也能够声明为虚函数。

槽的声明也是在头文件中进行的。

public slots:

void setValue(int value);

自定义槽

只有QObject的子类才能自定义槽

定义槽的类必须在类声明的最开始处使用Q_OBJECT

类中声明槽是需要使用slots关键字

槽与所处理的信号在函数签名上必须一致

SIGNAL与SLOT指定的名称中可以包含参数类型,不能包含具体的参数名

错误Object::connect:No such slot

A、检查类对象是否继承自QObject

B、检查类声明的开始处是否添加Q_OBJECT

C、检查是否使用slots对槽进行声明

D、检查槽的名称偏斜是否错误

E、重新编译工程

3、信号与槽的关联

通过调用QObject对象的connect函数来将某个对象的信号与另外一个对象的槽函数相关联,当发射者对象发射信号时,接收者对象的槽函数将被调用。connect函数的定义如下:

bool QObject::connect ( const QObject * sender, const char * signal, const QObject * receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection )

connect函数的作用就是将发射者sender对象中的信号signal与接收者receiver中的method槽函数联系起来。当指定信号signal时必须使用QT的宏SIGNAL(),当指定槽函数时必须使用宏SLOT()。如果发射者与接收者属于同一个对象的话,那么在connect 调用中接收者参数可以省略。

一个信号能够与另一个信号相关联,此时发射者发出信号后接收者的信号也会接着发射。

当信号与槽没有必要继续保持关联时,可以使用disconnect函数来断开连接。

bool QObject::disconnect ( const QObject * sender, const char * signal, const QObject * receiver, const char *method )

disconnect函数断开发射者中的信号与接收者中的槽函数之间的关联。

在disconnect函数中0可以用作一个通配符,分别表示任何信号、任何接收对象、接收对象中的任何槽函数。但是发射者sender不能为0,其它三个参数的值可以等于0。

以下三种情况需要使用disconnect()函数断开信号与槽的关联:

A、断开与某个对象相关联的任何对象

disconnect(sender, 0, 0, 0);

sender->disconnect();

B、断开与某个特定信号的任何关联

disconnect(sender, SIGNAL(mySignal()), 0, 0);

sender->disconnect(SIGNAL(mySignal()));

C、断开两个对象之间的关联

disconnect(sender, 0, receiver, 0);

sender->disconnect(receiver);

Qt利用信号与槽(signals/slots)机制取代传统的callback来进行对象之间的沟通。当操作事件发生的时候,对象会发提交一个信号(signal);而槽(slot)则是一个函数接受特定信号并且运行槽本身设置的动作。信号与槽之间,则通过QObject的静态方法connect来链接。

信号在任何运行点上皆可发射,甚至可以在槽里再发射另一个信号,信号与槽的链接不限定为一对一的链接,一个信号可以链接到多个槽或多个信号链接到同一个槽,甚至信号也可连接到信号。

以往的callback缺乏类型安全,在调用处理函数时,无法确定是传递正确型态的参数。但信号和其接受的槽之间传递的数据型态必须要相符合,否则编译器会提出警告。信号和槽可接受任何数量、任何型态的参数,所以信号与槽机制是完全类型安全。

信号与槽机制也确保了低耦合性,发送信号的类的并不知道是哪个槽会接受,也就是说一个信号可以调用所有可用的槽。此机制会确保当在"连接"信号和槽时,槽会接受信号的参数并且正确运行。

4、元对象工具

元对象编译器moc(meta object compiler)对C++文件中的类声明进行分析并产生用于初始化元对象的C++代码,元对象包含全部信号和槽的名字以及指向槽函数的指针。

moc读C++源文件,如果发现有Q_OBJECT宏声明的类,就会生成另外一个C++源文件,新生成的文件中包含有该类的元对象代码。例如,假设我们有一个头文件mysignal.h,在这个文件中包含有信号或槽的声明,那么在编译之前 moc 工具就会根据该文件自动生成一个名为mysignal.moc.h的C++源文件并将其提交给编译器;对应于mysignal.cpp文件moc工具将自动生成一个名为mysignal.moc.cpp文件提交给编译器。

元对象代码是signal/slot机制所必须的。用moc产生的C++源文件必须与类实现一起进行编译和连接,或者用#include语句将其包含到类的源文件中。moc并不扩展#include或者#define宏定义,只是简单的跳过所遇到的任何预处理指令。

信号和槽函数的声明一般位于头文件中,同时在类声明的开始位置必须加上Q_OBJECT语句,Q_OBJECT语句将告诉编译器在编译之前必须先应用moc工具进行扩展。关键字signals是对信号的声明,siganls没有public、private、protected等属性,slots是对槽函数的声明,slots有public、private、protected等属性。signals、slots关键字是QT 自己定义的,不是C++中的关键字。

信号的声明类似于函数的声明而非变量的声明,左边要有类型,右边要有括号,如果要向槽中传递参数的话,在括号中指定每个形式参数的类型,当然,形式参数的个数可以多于一个。

关键字slots指出随后开始槽的声明,这里slots用的也是复数形式。

槽的声明与普通函数的声明一样,可以携带零或多个形式参数。既然信号的声明类似于普通C++函数的声明,那么,信号也可采用C++中虚函数的形式进 行声明,即同名但参数不同。例如,第一次定义的void mySignal()没有带参数,而第二次定义的却带有参数,从这里我们可以看到QT的信号机制是非常灵活的。

信号与槽之间的联系必须事先用connect函数进行指定。如果要断开二者之间的联系,可以使用函数disconnect。

5、信号与槽机制的局限

信号与槽是一种高效灵活的通信机制,但有其缺陷:

A、信号与槽的非常高效的,但是与回调函数相比,由于增加了灵活性,因此在速度上有所损失,这种损失相对来说是比较小的,通过在一台i586-133的机器上测试是10微秒(运行Linux),可见这种机制所提供的简洁性、灵活性还是值得的。一般来说,在实时系统中就要尽可能的少用信号与槽机制。

B、信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也有可能产生死循环。因此,在定义槽函数时一定要避免在槽函数中再次发射所接收到的同样信号。

C、如果一个信号与多个槽相关联,那么当这个信号被发射时,与之相关的槽函数被调用的顺序将是随机的。

D、宏定义不能用在信号和槽的参数中。

moc工具不扩展#define,在信号和槽的参数中使用宏将不能正确地工作,不带参数是可以的。

E、构造函数不能用在signals或者slots声明区域内。

F、函数指针不能作为信号或槽的参数。

函数指针作为参数是不合语法,但可以使用typedef将函数指针类型重命名,使用函数指针类型作为参数是合语法的。

G、信号与槽不能有缺省参数。

H、信号与槽也不能使用模板类参数

可以使用typedef重命名模板类,重命名后的类型名可以作为信号与槽的参数

I、嵌套的类不能位于信号或槽区域内,也不能有信号或者槽。

J、友元声明不能位于信号或者槽声明区内,应该在普通C++的private、protected或者public区内进行声明。

时间: 2024-12-28 01:47:53

QT开发(十三)——QT信号与槽机制的相关文章

QT的信号和槽机制简介

信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注意的一些问题. QT是一个跨平台的C++ GUI应用构架,它提供了丰富的窗口部件集,具有面向对象.易于扩展.真正的组件编程等特点,更为引人注目的是目前Linux上最为流行的KDE桌面环境就是建立在QT库的基础之上.QT支持下列平台:MS/WINDOWS-95.98.NT和2000:UNIX/X11-Linux.Sun Solaris.HP-UX.Digital Unix.IB

QT的信号与槽机制介绍

信号与槽作为QT的核心机制在QT编程中有着广泛的应用,本文介绍了信号与槽的一些基本概念.元对象工具以及在实际使用过程中应注意的一些问题. QT是一个跨平台的C++ GUI应用构架,它提供了丰富的窗口部件集,具有面向对象.易于扩展.真正的组件编程等特点,更为引人注目的是目前Linux上最为流行的KDE桌面环境就是建立在QT库的基础之上.QT支持下列平台:MS/WINDOWS-95.98.NT和2000:UNIX/X11-Linux.Sun Solaris.HP-UX.Digital Unix.IB

Qt的信号与槽机制

1.信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解. 2.信号和槽是一种高级接口,应用于对象之间的通信,它是QT的核心特性,也是QT区别于其它工具包的重要地方. 3.信号和槽是QT自行定义的一种通信机制,它独立于标准的C/C++语言,因此要正确的处理信号和槽,必须借助一个称为moc(Meta Object Compiler)的QT工具,该工具是一个C++预处理程序,它为高层次的事件处理自动生成所需要的附加代码. 4.在我们所熟知的很多GUI工具包中,窗口小部件(widget

Qt源码分析之信号和槽机制

Qt的信号和槽机制是Qt的一大特点,实际上这是和MFC中的消息映射机制相似的东西,要完成的事情也差不多,就是发送一个消息然后让其它窗口响应,当然,这里的消息是广义的说法,简单点说就是如何在一个类的一个函数中触发另一个类的另一个函数调用,而且还要把相关的参数传递过去.好像这和回调函数也有点关系,但是消息机制可比回调函数有用多了,也复杂多了 MFC中的消息机制没有采用C++中的虚函数机制,原因是消息太多,虚函数开销太大.在Qt中也没有采用C++中的虚函数机制,原因与此相同.其实这里还有更深层次上的原

关于Qt信号与槽机制的传递方向性研究(结论其实是错误的,但是可以看看分析过程)

最近由于项目的需求,一直在研究Qt.信号与槽机制是Qt的一大特色,该机制允许两者间传递参数,依次来实现对象间的通信.这个参数会分别存在于信号的参数列表和槽函数的参数列表中.需要注意的是,若将槽函数绑定至信号,槽函数的参数列表元素数目只能少于等于信号的参数列表元素数目.而且顺序和类型不能改变.至于缺少的参数应从信号参数尾部开始缺少. 突然今天想起来一个问题,如果一个对象发出信号,将内部的一个成员变量(非简单类型)作为参数向外发送,槽函数就可以接收到这个对象,那么槽函数是否可以完全操作这个对象呢?如

qt中信号与槽机制

一. 简介 就我个人来理解,信号槽机制与Windows下消息机制类似,消息机制是基于回调函数,Qt中用信号与槽来代替函数指针,使程序更安全简洁. 信号和槽机制是 Qt 的核心机制,可以让编程人员将互不相关的对象绑定在一起,实现对象之间的通信. 信号 当对象改变其状态时,信号就由该对象发射 (emit) 出去,而且对象只负责发送信号,它不知道另一端是谁在接收这个信号.这样就做到了真正的信息封装,能确保对象被当作一个真正的软件组件来使用. 槽 用于接收信号,而且槽只是普通的对象成员函数.一个槽并不知

Qt源码分析之信号和槽机制(QMetaObject是一个内部struct)

Qt的信号和槽机制是Qt的一大特点,实际上这是和MFC中的消息映射机制相似的东西,要完成的事情也差不多,就是发送一个消息然后让其它窗口响应,当然,这里的消息是广义的说法,简单点说就是如何在一个类的一个函数中触发另一个类的另一个函数调用,而且还要把相关的参数传递过去.好像这和回调函数也有点关系,但是消息机制可比回调函数有用多了,也复杂多了 MFC中的消息机制没有采用C++中的虚函数机制,原因是消息太多,虚函数开销太大.在Qt中也没有采用C++中的虚函数机制,原因与此相同.其实这里还有更深层次上的原

QT信号与槽机制需要注意的问题

1.信号与槽的效率是非常高的,但是同真正的回调函数比较起来,由于增加了灵活性,因此在速度上还是有所损失.当然这种损失相对来说是比较小的,但是要追求高效率的话,比如实时系统,就要尽可能避免. 2.信号与槽机制与普通函数的调用一样,如果使用不当的话,在程序执行时也可能产生死循环.因此,在定义槽函数时一定要注意避免间接形成无限循环,即在槽中再次发送所接收到的同样信号,防止死循环. 3.如果一个信号与多个槽相联系的话,那么,当这个信号被发射时,与之相关的槽被激活的顺序将是随机的. 4.宏定义不能用在si

QT学习小结之信号与槽

信号与槽函数是我们学习QT必备的基础知识,今天跟大家分享我学习QT的一些总结吧. 信号槽机制是Qt编程的基础.通过信号槽,能够使Qt各组件在不知道对方的情形下能够相互通讯. 槽函数和普通的C++成员函数没有很大的区别.它们也可以使virtual的:可以被重写:可以使public.protected或者private的:可以由其它的C++函数调用:参数可以是任何类型的.如果要说区别,那就是,槽函数可以和一个信号相连接,当这个信号发生时,它可以被自动调用. 信号与槽函数的连接我们可以用connect