Qt为了方便一些事情的处理,引入了信号(Signal)的概念,封装了一些事件操作的标准预处理,使得用户不必去处理底层事件,只需要处理信号即可。Qt还定义了一些预定义信号。在某些事件处理函数中会发送预定义信号,如果用户添加了与该信号相连的信号处理函数(也叫槽函数),则调用该槽函数。当然,并不是所有事件处理函数都会有信号发送。除了预定义信号外,用户也可以自己发送自定义信号。
信号与槽(Slot)其实都是函数。当特定事件被触发时(如在编辑框输入了字符)将发送一个信号,与之连接的槽则可以接收到并做出响应。
信号类似Windows编程中的消息,槽类似于消息处理函数。比如,鼠标的按钮被单击,就会发出名为clicked的信号,如果该信号连接了槽(函数),就会调用这个函数来进行处理。这个发出时没有目的的,类似广播。如果有对象对这个信号感兴趣,它就会使用连接(connect)函数,意思是将想要处理的信号和自己的一个函数(槽)绑定来进行处理。也就是说,当信号发出时,被连接的槽函数会自动被回调。
信号和槽是Qt特有的信息传输机制,是Qt程序设计的重要基础,可以让互不干扰的对象建立一种联系。
槽的本质是类的成员函数,它的参数可以是任意类型,和普通C++成员函数几乎没有区别,可以是虚函数,可以被重载,可以是公有的,保护的,私有的,也可以被其他C++成员函数调用。唯一的区别是:槽可以与信号连接在一起,每当和槽连接的信号被发出时,就会调用这个槽。
信号和槽是多对多的关系。一个信号可以连接多个槽,一个槽也可以监听多个信号。
信号可以有附加信息。例如,窗口关闭的时候可能发出windowClosing信号,这个信号可以包含窗口的句柄,用来表明究竟是哪个窗口发出的;一个滑块在滑动时可能发出一个信号,包含滑块的具体位置或者新的值等。
信号和槽的机制实际是与语言无关的,有很多方法都可以实现信号和槽的机制,不同的实现机制会导致信号和槽的差别很大。信号和槽这一术语最初来自Trolltech(奇趣)公司的Qt库(后来被Nokia收购)。1994年,Qt的第一个版本发布后,为我们带来了信号和槽的概念。
需要注意的是,connect()函数只能在QObject类和QObject派生类中使用,在自己新建的类(基类不是QObject类和QObject派生类)中使用connect()函数是无效的,编译时会一直报错。
QMetaObject::Connection QObject::connect(const QObject *sender, const char* signal, const QObject *receiver, const char *method, Qt::ConnectionType type = Qt::AutoConnection())
- signals前面不可加public、private和protected进行修饰;
- slots前面可加public、private和protected进行修饰;因为槽函数可以当普通函数使用。
- signals区域的函数必须是void类型,而且这些信号函数没有函数体,也就是说不可以自己定义这些信号函数,我们只要声明它,剩下QT内部会自己处理。
- 宏定义和函数指针不能用于信号和槽函数,信号和槽也不能有缺省函数。
- 信号的声明是在头文件中进行的,QT的signals关键字指出了信号声明区,下面定义了三个信号:
signals:
void mySignals();
void mySiganls(int s);
void mySignalParam(int x,int y);
2.槽函数也分为三种类型,即public slots、private slots和protected slots。
public slots:在这个区内声明的槽意味着所有对象都可将信号和之相连接。这对于组件编程非常有用.
protected slots:在这个区内声明的槽意味着当前类及其子类能将信号和之相连接。这适用于那些槽,他们是类实现的一部分,不过其界面接口却面向外部。
private slots:在这个区内声明的槽意味着只有类自己能将信号和之相连接。这适用于联系非常紧密的类。
槽也能够声明为虚函数,这也是非常有用的。
槽的声明也是在头文件中进行的。例如,下面声明了三个槽:
public slots:
void mySlot();
void mySlot(int x);
void mySignalParam(int x,int y);
后续应该注意事项:参考文章末尾:
(6.函数指针不能作为信号或槽的参数。--解决方式)
Signals和Slot的使用
网友评论