信号和槽机制是 QT 的核心机制 。信号和槽是一种高级接口,应用于对象之间的通信,它是 QT 的核心特性,也是 QT 区别于其它工具包的重要地方。信号和槽是 QT 自行定义的一种通信机制,它独立于标准的 C/C++ 语言,因此要正确的处理信号和槽,必须借助一个称为 moc(Meta Object Compiler)的 QT 工具,该工具是一个 C++ 预处理程序,它为高层次的事件处理自动生成所需要的附加代码。
在QT中,connect()函数是关联部件的动作与执行的函数。
在启动函数中进行设置,并非是在信号槽函数中进行设置。也就是一启动就关联好,如果放在信号槽中,则进行第一次动作,进行关联,第二次才能实行执行的函数。
同时,connect()函数中的SLOT()中的槽函数,必须在头文件定义中需要放在public slot或者private slot函数中。否则不能实现,编译错误。
信号和槽能携带任意数量和任意类型的参数(类型要匹配),他们是类型完全安全的,不会像回调函数那样产生 core dumps。
所有从 QObject 或其子类 ( 例如 Qwidget) 派生的类都能够包含信号和槽。当对象改变其状态时,信号就由该对象发射 (emit) 出去,它不知道另一端是谁在接收这个信号。这就是真正的信息封装,它确保对象被当作一个真正的软件组件来使用。槽用于接收信号,但它们是普通的对象成员函数。一个槽并不知道是否有任何信号与自己相连接。而且,对象并不了解具体的通信机制
槽(Slots):
槽是普通的 C++ 成员函数,可以被正常调用,它们唯一的特殊性就是很多信号可以与其相关联。当与其关联的信号被发射时,这个槽就会被调用。槽可以有参数,但槽的参数不能有缺省值。
既然槽是普通的成员函数,因此与其它的函数一样,它们也有存取权限。槽的存取权限决定了谁能够与其相关联。同普通的 C++ 成员函数一样,槽函数也分为三种类型,即 public slots、private slots 和 protected slots。 // 与C++三种权限作用相同;;
- public slots:在这个区内声明的槽意味着任何对象都可将信号与之相连接。这对于组件编程非常有用,你可以创建彼此互不了解的对象,将它们的信号与槽进行连接以便信息能够正确的传递。
- protected slots:在这个区内声明的槽意味着当前类及其子类可以将信号与之相连接。这适用于那些槽,它们是类实现的一部分,但是其界面接口却面向外部。
- private slots:在这个区内声明的槽意味着只有类自己可以将信号与之相连接。这适用于联系非常紧密的类。
槽也能够声明为虚函数,这也是非常有用的。// 被继承使用;;
信号(Signals):
当某个信号对其客户或所有者发生的内部状态发生改变,信号被一个对象发射(emit)。只有 定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,与其相关联的槽将被立刻执行,就象一个正常的函数调用一样。信号 - 槽机制完全独立于任何 GUI 事件循环。只有当所有的槽返回以后发射函数(emit)才返回。 如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地 执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪 个后执行。
信号的声明是在头文件中进行的,QT 的 signals 关键字指出进入了信号声明区,随后即可 声明自己的信号。
信号与槽关联 Connect()函数:
通过调用 QObject 对象的 connect 函数来将某个对象的信号与另外一个对象的槽函数相关联,这样当发射者发射信号时,接收者的槽函数将被调用
一般使用一下两种格式:
1、 QMetaObject::Connection QObject::connect(const QObject * sender, const char * signal, const QObject * receiver, const char * method, Qt::ConnectionType type = Qt::AutoConnection) [static] QLabel *label = new QLabel; QScrollBar *scrollBar = new QScrollBar; QObject::connect(scrollBar, SIGNAL(valueChanged(int)),label, SLOT(setNum(int))); // 使用 SIGNAL() 与 SLOT() 宏;; 2、QMetaObject::Connection QObject::connect(const QObject * sender, PointerToMemberFunction signal, const QObject * receiver, PointerToMemberFunction method, Qt::ConnectionType type = Qt::AutoConnection) [static] QLabel *label = new QLabel; QLineEdit *lineEdit = new QLineEdit; QObject::connect(lineEdit, &QLineEdit::textChanged,label, &QLabel::setText); // 使用实例地址进行引用信号 与 槽
当信号与槽没有必要继续保持关联时,我们可以使用 disconnect 函数来断开连接。如下定义:
bool QObject::disconnect ( const QObject * sender, const char * signal, const Object * receiver, const char * member ) [static]
1、Disconnect everything connected to an object‘s signals:
disconnect(myObject, 0, 0, 0);
等于 myObject->disconnect();
2、Disconnect everything connected to a specific signal:
disconnect(myObject, SIGNAL(mySignal()), 0, 0);
等于 myObject->disconnect(SIGNAL(mySignal()));
3、Disconnect a specific receiver:
disconnect(myObject, 0, myReceiver, 0);
等于 myObject->disconnect(myReceiver);
0 may be used as a wildcard, meaning "any signal", "any receiving object", or "any slot in the receiving object", respectively.
The sender may never be 0. (You cannot disconnect signals from more than one object in a single call.)
If signal is 0, it disconnects receiver and method from any signal. If not, only the specified signal is disconnected.
If receiver is 0, it disconnects anything connected to signal. If not, slots in objects other than receiver are not disconnected.
If method is 0, it disconnects anything that is connected to receiver. If not, only slots named method will be disconnected, and all other slots are left alone. The method must be 0 if receiver is left out, so you cannot disconnect a specifically-named slot on all objects.