Qt信号和槽机制

概述

信号和槽机制是QT的核心机制,要精通QT编程就必须对信号和槽有所了解。信号和槽是一种高级接口,应用于对象之间的通信,他是QT的核心特性,也是QT差别于其他工具包的重要地方。信号和槽是QT自行定义的一种通信机制,他独立于标准的C/C+ +语言,因此要正确的处理信号和槽,必须借助一个称为moc(Meta Object Compiler)的QT工具,该工具是个C++预处理程式,他为高层次的事件处理自动生成所需要的附加代码。
在我们所熟知的非常多GUI工具包中,窗口小部件(widget)都有一个回调函数用于响应他们能触发的每个动作,这个回调函数通常是个指向某个函数的指针。不过,在 QT中信号和槽取代了这些凌乱的函数指针,使得我们编写这些通信程式更为简洁明了。信号和槽能携带任意数量和任意类型的参数,他们是类型完全安全的,不会像回调函数那样产生core dumps。
所有从QObject或其子类(例如Qwidget)派生的类都能够包含信号和槽。当对象改动其状态时,信号就由该对象发射(emit)出去,这就是对象所要做的全部事情,他不知道另一端是谁在接收这个信号。这就是真正的信息封装,他确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但他们是普通的对象成员函数。一个槽并不知道是否有所有信号和自己相连接。而且,对象并不了解具体的通信机制。
你能将非常多信号和单个的槽进行连接,也能将单个的信号和非常多的槽进行连接,甚至于将一个信号和另外一个信号相连接也是可能的,这时无论第一个信号什么时候发射系统都将即时发射第二个信号。总之,信号和槽构造了一个强大的部件编程机制。

程序示例:

这里给出了一个简单的样例程式,程式中定义了三个信号、三个槽函数,然后将信号和槽进行了关联,每个槽函数只是简单的弹出一个对话框窗口。读者能用kdevelop生成一个简单的QT应用程式,然后将下面的代码添加到相应的程式中去。
信号和槽函数的声明一般位于头文件中,同时在类声明的开始位置必须加上Q_OBJECT语句,这条语句是不可缺少的,他将告诉编译器在编译之前必须先应用 moc工具进行扩展。关键字signals指出随后开始信号的声明,这里signals用的是复数形式而非单数,siganls没有public、 private、protected等属性,这点不同于slots。另外,signals、slots关键字是QT自己定义的,不是C+ +中的关键字。
信号的声明类似于函数的声明而非变量的声明,左边要有类型,右边要有括号,如果要向槽中传递参数的话,在括号中指定每个形式参数的类型,当然,形式参数的个数能多于一个。
关键字slots指出随后开始槽的声明,这里slots用的也是复数形式。
槽的声明和普通函数的声明相同,能携带零或多个形式参数。既然信号的声明类似于普通C+ +函数的声明,那么,信号也可采用C++中虚函数的形式进行声明,即同名但参数不同。例如,第一次定义的void mySignal()没有带参数,而第二次定义的却带有参数,从这里我们能看到QT的信号机制是非常灵活的。
信号和槽之间的联系必须事先用connect函数进行指定。如果要断开二者之间的联系,能使用函数disconnect。

//tsignal.h 
… 
class TsignalApp:public QMainWindow 
{ 
Q_OBJECT 
… 
//信号声明区 
signals: 
//声明信号mySignal() 
void mySignal(); 
//声明信号mySignal(int) 
void mySignal(int x); 
//声明信号mySignalParam(int,int) 
void mySignalParam(int x,int y); 
//槽声明区 
public slots: 
//声明槽函数mySlot() 
void mySlot(); 
//声明槽函数mySlot(int) 
void mySlot(int x); 
//声明槽函数mySignalParam (int,int) 
void mySignalParam(int x,int y); 
} 
… 
//tsignal.cpp 
… 
TsignalApp::TsignalApp() 
{ 
… 
//将信号mySignal()和槽mySlot()相关联 
connect(this,SIGNAL(mySignal()),SLOT(mySlot())); 
//将信号mySignal(int)和槽mySlot(int)相关联 
connect(this,SIGNAL(mySignal(int)),SLOT(mySlot(int))); 
//将信号mySignalParam(int,int)和槽mySlotParam(int,int)相关联 
connect(this,SIGNAL(mySignalParam(int,int)),SLOT(mySlotParam(int,int))); 
} 
// 定义槽函数mySlot() 
void TsignalApp::mySlot() 
{ 
QMessageBox::about(this,”Tsignal”, “This is a signal/slot sample without 
parameter.”); 
} 
// 定义槽函数mySlot(int) 
void TsignalApp::mySlot(int x) 
{ 
QMessageBox::about(this,”Tsignal”, “This is a signal/slot sample with one 
parameter.”); 
} 
// 定义槽函数mySlotParam(int,int) 
void TsignalApp::mySlotParam(int x,int y) 
{ 
char s[256]; 
sprintf(s,”x:%d y:%d”,x,y); 
QMessageBox::about(this,”Tsignal”, s); 
} 
void TsignalApp::slotFileNew() 
{ 
//发射信号mySignal() 
emit mySignal(); 
//发射信号mySignal(int) 
emit mySignal(5); 
//发射信号mySignalParam(5,100) 
emit mySignalParam(5,100); 
}

【更多参考】

posted @ 2019-04-01 14:48  Z--Y  阅读(1731)  评论(0编辑  收藏  举报