Chinaunix首页 | 论坛 | 博客
  • 博客访问: 631760
  • 博文数量: 1008
  • 博客积分: 10
  • 博客等级: 民兵
  • 技术积分: 5175
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-31 09:44
文章分类
文章存档

2012年(1008)

我的朋友

分类:

2012-08-01 11:02:32

原文地址:Signal 和Slot 机制 作者:luozhiyong131

Qt中,有一种用于对象之间的通信:信号-槽机制,这种机制是Qt的核心机制,也是它区别于其他GUI工具的最主要的特征。信号-槽机制可以携带任意类型、任意数量的参数,而且完全是安全的,不会引起系统的崩溃。用户可以按照需要将许多信号与一个单独的槽函数相联系,一个信号也可以按需要被联系到很多不同的槽函数。甚至还可以将一个信号直接与另一个信号相联系,这样当第一个信号被发出时立刻发出第二个信号。

当某个信号所对应的客户或其所有者的内部状态发生改变时,信号被一个对象发射。只有定义过这个信号的类及其派生类能够发射这个信号。当一个信号被发射时,与其相关联的

槽将被立刻执行,就象调用一个正常的函数一样。信号-槽机制完全独立于任何GUI事件循环。只有当所有的槽返回以后发射函数(emit)才返回。如果存在多个槽与某个信号相关联,那么,当这个信号被发射时,这些槽将会一个接一个地执行,但是它们执行的顺序将会是随机的、不确定的,我们不能人为地指定哪个先执行、哪个后执行。例如,一个列表框可以发出highlighted()activated()的信号,大多数对象也许只对activated()的信号感兴趣,但也许

有些对象需要知道该列表框中的哪一项被选中了。如果有两个不同的对象对一个信号感兴趣,只要将该信号连接到这两个对象的槽上就可以了。

Signal和Slot的声明

Qt程序设计中,凡是包含signalslot的类中都要加上Q_OBJECT的定义,下面的例子给出了如何在一个类中定义signalslot

class Student : public QObject

{

Q_OBJECT

public:

Student() { myMark = 0; }

int mark() const { return myMark; }

public slots:

void setMark(int newMark);

signals:

void markChanged(int newMark);

private:

int myMark;

};

signalslot在类体内通常声明为void型成员函数,允许带参数signal 不需要实体,slot必须要有实体,否则错误就同声明一个函数却没有实体一样,会发生链接错误

signal的发出一般在事件的处理函数中,利用emit发出signal,在下面的例子中在在事件处理结束后发出signal

void Student::setMark(int newMark)

{

if (newMark!= myMark) {

myMark = newMark;

emit markChanged(myMark);

}

}

Signal和Slot的连接

signalslot声明以后,需要使用connect()函数将它们连接起来。connect()函数属于QObject类的成员函数,它能够连接signalslot,也可以用来连接signalsignal函数原形如下:

bool connect ( const QObject * sender, const char * signal,const char * member ) const

其中第一个和第三个参数分别指出signalslot是属于那个对象或组件

在使用connect()函数进行来接的时候,还需要用到SIGNAL()SLOT()这两个宏,使用方法如下:

QLabel *label = new QLabel;

QScrollBar *scroll = new QScrollBar;

QObject::connect( scroll,SIGNAL(valueChanged(int)),label, SLOT(setNum(int)) );

同一个信号连接多个插槽

connect(slider, SIGNAL(valueChanged(int)),spinBox,SLOT(setValue(int)));

connect(slider,SIGNAL(valueChanged(int)),this,SLOT(updateStatusBarIndicator(int)));

多个信号连接到同一个插槽

connect(lcd, SIGNAL(overflow()),this,SLOT(handleMathError()));

connect(calculator, SIGNAL(divisionByZero()),this,SLOT(handleMathError()));

一个信号连接到另一个信号

connect(lineEdit, SIGNAL(textChanged(const QString&)),this, SIGNAL(updateRecord(const QString&)));

 取消一个连接

disconnect(lcd,SIGNAL(overflow()),this,SLOT(handleMathError()));

取消一个连接不是很常用,因为Qt会在一个对象被删除后自动取消这个对象所包含的所有的连接

阅读(265) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~