Qt 信号槽整理

1、信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,他是QT的核心特性,也是QT差别于其他工具包的重要地方。信号和槽是QT自行定义的一种通信机制,他独立于标准的C/C++语言,因此要正确的处理信号和槽,必须借助一个称为moc(Meta Object Compiler)的QT工具,该工具是个C++预处理程式,他为高层次的事件处理自动生成所需要的附加代码。 使用信号槽时要先声明Q_OBJECT

1、signals前面不可加public、private和protected进行修饰;slots前面可以加,因为Qt说槽函数可以当普通函数使用。

2、signals区域的函数必须是void类型,而且这些信号函数没有函数体,也就是说不可以自己定义这些信号函数,你只要声明它就够了,其它不用管,Qt内部自己弄。

3、宏定义和函数指针不能用于信号和槽的参数,信号和槽也不能有缺省参数。

2、信号 
当某个信号对其客户或所有者发生的内部状态发生改动,信号被一个对象发射。只有定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,和其相关联的槽将被即时执行,就象一个正常的函数调用相同。信号-槽机制完全独立于所有GUI事件循环。只有当所有的槽返回以后发射函数(emit)才返回。如果存在多个槽和某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,不过他们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪个后执行。 
信号的声明是在头文件中进行的,QT的signals关键字指出进入了信号声明区,随后即可声明自己的信号。例如,下面定义了三个信号: 
signals: 
void mySignal(); 
void mySignal(int x); 
void mySignalParam(int x,int y); 
在上面的定义中,signals是QT的关键字,而非C/C++的。接下来的一行void mySignal() 定义了信号mySignal,这个信号没有携带参数;接下来的一行void mySignal(int x)定义了重名信号mySignal,不过他携带一个整形参数,这有点类似于C++中的虚函数。从形式上讲信号的声明和普通的C++函数是相同的,不过信号却没有函数体定义,另外,信号的返回类型都是void,不要指望能从信号返回什么有用信息。 

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

3、槽 

槽是普通的C++成员函数,能被正常调用,他们唯一的特别性就是非常多信号能和其相关联。当和其关联的信号被发射时,这个槽就会被调用。槽能有参数,但槽的参数不能有缺省值。 
同普通的C++成员函数相同,槽函数也分为三种类型,即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);

4、使用中遇到的情况总结

扫描二维码关注公众号,回复: 45152 查看本文章

(1) 同一线程两个不同的类

 如某一panel有一个button,希望点击该btn的时候处于另一个类(如Controller)里的槽函数响应。

实现过程:panel.h

signals:
    void SignalClickCancelBtn();

panel.cpp

 bool bConnect = false;
 bConnect=connect(m_btnCancel, &Dx3DPushButton::clicked,this, &DxRestoreSessionPanel::SignalClickCancelBtn);
 Q_ASSERT(bConnect);

controller.cpp

bool bIsConnect = false;
bIsConnect = connect(m_Panel,&DxRestoreSessionPanel::SignalClickCancelBtn,
			this,&DxBaseMainController::SlotClickRestoreSessionPanelCancelButton);
Q_ASSERT(bIsConnect); 

并实现

SlotClickRestoreSessionPanelCancelButton();

(2) 不同线程间用信号槽通信

和上面两个类通信没有什么区别,只要保证信号发出是在connect之后就可以了,还有在线程间使用信号槽进行通信时,需要注意必须使用元数据类型,Qt内生的元数据类型,如int double QString 等,如果要用自己定义的数据类型,需要在connect前将其注册为元数据类型。如:

qRegisterMetaType<Msg>("Msg");  



猜你喜欢

转载自blog.csdn.net/Zzhouzhou237/article/details/80019326