Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1480592
  • 博文数量: 181
  • 博客积分: 3308
  • 博客等级: 中校
  • 技术积分: 2227
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-03 12:03
个人简介

我是zoro

文章分类

全部博文(181)

文章存档

2015年(1)

2013年(35)

2012年(39)

2011年(50)

2010年(56)

分类: LINUX

2010-10-28 18:51:13

信号和槽

Signals and slots are used for communication between objects. The signals and slots mechanism is a central feature of Qt and probably the part that differs most from the features provided by other frameworks.
信号和槽用于对象间的通信。信号和槽机制是QT的核心特色,也可能是QT与别的框架设计结构最为不同的方面。

Introduction

In GUI programming, when we change one widget, we often want another widget to be notified. More generally, we want objects of any kind to be able to communicate with one another. For example, if a user clicks a Close button, we probably want the window's function to be called.

Older toolkits achieve this kind of communication using callbacks. A callback is a pointer to a function, so if you want a processing function to notify you about some event you pass a pointer to another function (the callback) to the processing function. The processing function then calls the callback when appropriate. Callbacks have two fundamental flaws: Firstly, they are not type-safe. We can never be certain that the processing function will call the callback with the correct arguments. Secondly, the callback is strongly coupled to the processing function since the processing function must know which callback to call.

简介:
  在图形用户界面编程中
,当改变一个窗口的时候,我们经常希望另一个窗口部件被通知到。更多的时候,我们希望任一类的对象能够与其它的对象间能够相互通信。例如:如果一个用户单击一个Close按钮,我们通常想的是窗口的close()函数能被调用。
     
    较老的工具包实现这种功能是通过使用回调函数。回调函数是一个指向函数的指针,因此,如果你想一个处理函数去通知你一些事件,你可以把另一个函数(回调函数)的指针传递给处理函数。
然后处理函数在合适的时机调用回调函数。回调函数有两个最基本的缺点:首先,它们不是类型安全的。我们从来都不能确定处理函数使用了正确的参数来调用回调。其次,回调和处理函数是非常强有力地联系在一起的,因为处理函数必须知道 要调用哪个回调。

Signals and Slots

In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in reponse to a particular signal. Qt's widgets have many pre-defined slots, but it is common practice to subclass widgets and add your own slots so that you can handle the signals that you are interested in.

信号和槽
   在Qt中我们有一种可以替代回调的技术:我们使用信号和槽。当一个特定事件发生的时候,一个信号被发出。Qt的窗口部件有很多预定义的信号,但是我们总是可以通过继承来加入我们自己的信号。槽就是一个可以被调用处理特定信号的函数。Qt的窗口部件又很多预定义的槽,但是通常的习惯是你可以加入自己的槽,这样你就可以处理你所感兴趣的信号。
The signals and slots mechanism is type safe: The signature of a signal must match the signature of the receiving slot. (In fact a slot may have a shorter signature than the signal it receives because it can ignore extra arguments.) Since the signatures are compatible, the compiler can help us detect type mismatches. Signals and slots are loosely coupled: A class which emits a signal neither knows nor cares which slots receive the signal. Qt's signals and slots mechanism ensures that if you connect a signal to a slot, the slot will be called with the signal's parameters at the right time. Signals and slots can take any number of arguments of any type. They are completely type safe.
   信号和槽的机制是类型安全的:一个信号的签名必须与它的接收槽的签名相匹配。(实际上一个 槽的签名可以比它接收的信号的签名少,因为它可以忽略额外的参数。)因为签名是一致的,编译器就可以帮助我们检测类型不匹配。信号和槽是宽松地联系在一起的:一个发射信号的类不用知道也不用注意哪个槽要接收这个信 号。Qt的信号和槽的机制可以保证如果你把一个信号和一个槽连接起来,槽会在正确的时间使用信号的参数而被调用。信号和槽可以使用任何数量、任何类型的参数。它们是完全类型安全的。

   All classes that inherit from QObject or one of its subclasses (e.g.,QWidget) can contain signals and slots. Signals are emitted by objects when they change their state in a way that may be interesting to other objects. This is all the object does to communicate. It does not know or care whether anything is receiving the signals it emits. This is true information encapsulation, and ensures that the object can be used as a software component.

      那些从QObject或者它的子类 (比如QWidget类)中继承下来的类包含它的信号和槽。 当对象
对其它对象感兴趣而改变它们的状态的时候,信号被发送。这就是所有的对象通信时所做的。它不知
道也不关心是否有谁在接收它发出的那些信号。这就是真正的信息封装,并且确保对象可以用作一个
软件组件。 Slots can be used for receiving signals, but they are also normal member functions.
 Just as an object does not know if anything receives its signals, a slot does not know if
it has any signals connected to it. This ensures that truly independent components can
be created with Qt. 槽可以用来接收信号,但它们同样也是标准的成员函数。就像一个对象不知道谁接收它的信号,
一个槽也不知道它是否有信号与它连接。这确保了在QT中建立正在独立的软件组件。 You can connect as many signals as you want to a single slot, and a signal can be
connected to as many slots as you need. It is even possible to connect a signal directly
to another signal. (This will emit the second signal immediately whenever the first is
emitted.) 你可以把多个信号和你所希望的单一槽相连,并且一个信号也可以和你所期望的多个槽连接。甚至
可以让一个信号和其它信号连接。(这时,只要第一个信号被发出,第二个信号立即被发送。) Together, signals and slots make up a powerful component programming mechanism. 总之,信号和槽构成了一个强大的组件编程机制。 一个简单的例子: 一个简单的C++类声明如下:   class Counter { public: Counter() { m_value = 0; } int value() const { return m_value; } void setValue(int value); private: int m_value; }; 一个基于QObject的类的声明: #include class Counter : public QObject { Q_OBJECT public: Counter() { m_value = 0; } int value() const { return m_value; } public slots: void setValue(int value); signals: void valueChanged(int newValue); private: int m_value; }; The QObject-based version has the same internal state, and provides public
methods to access the state, but in addition it has support for component programming
 using signals and slots. This class can tell the outside world that its state has changed
by emitting a signal, valueChanged(), and it has a slot which other objects can send
signals to. 基于QObject的类有着同样的内部状态和共有方法来访问状态,但是另外它也支持通过使用信号
和槽构成程序。这个类能够通过发送一个valueChanged()信号告诉外部它的状态发生了改变,而且
,它所对应的槽别的对象也可以发送信号来使用这个槽。 All classes that contain signals or slots must mention Q_OBJECT at the top of their
declaration. They must also derive (directly or indirectly) from QObject. Slots are implemented by the application programmer. Here is a possible
implementation of the Counter::setValue() slot: 所有包含信号或槽的类必须在它们的声明顶部包含Q_OBJECT。它们都是直接或间接地源于
Q_OBJECT 。 槽由程序员来实现。这里有一个 Counter::setValue()槽实现: void Counter::setValue(int value) { if (value != m_value) { m_value = value; emit valueChanged(value); } }
emit表示信号valueChanged()从对象中发送。带着一个新的值作为它的参数。

 下面是一个代码片段,我们建立两个Counter对象,然后通过使用QObject::connect()方法把第一个对象的valueChanged()信号和第二个对象的setValue()槽连接起来:
  Counter a,b;
 QObject::connect(&a,SIGNAL(valueChanged(int)),&b,SLOT(setValue(int));
 a.setValue(12);
 b.setValue(48);

调用一个a.setValue(12) 发送一个valueChanged(12)信号,b将用它的setValue()槽来接受这个信号。然后b同样的发送valueChanged()信号,但是由于没有槽和b的valueChanged()信号相连接,信号被忽略。

注意,setValue()槽是这么工作的,只有当value!=m_value的时候,才发送信号,这确保了循环连接不会导致无限循环了。

一个信号被你所做的每个连接发送,如果你写了两个连接,两个信号将被发送。你能够使用QObject::disconnect()函数来切断连接。

这个例子阐述了对象只需要连接在一起,就能够不需要知道相互的信息就可以工作在一起。

c++预处理器通过改变或者删除signals,slots和emit关键字,使程序变成标准的c++;

在那些包含信号和槽的类上运行moc,将产生一个c++源文件,这个源文件将被被的对象文件编译和连接。如果你使用qmake命令,makefile规则将自动的调用moc.

信号:
当一个对象感兴趣他的客户(object's client or owner),这在一些方面改变了他的内部的状态,那么对象的信号就要被发射。只有定义了信号的类和它的子类能够发射信号。

例如一个列表框发射一个click()和currentChanged()信号。很多对象可能只对currentChanged()信号感兴趣,这个信号的作用是当用户单击表项的时候,或者使用上下键移动它的时候,给出当前的表项( Most objects will probably only be interested in urrentChanged() which gives the current list item whether the user clicked it or used the arrow keys to move to it)。但是一些对象可能仅仅想知道那些表项被选中了。如果两个不同的信号感兴趣于同一个信号,可以把这个信号连接到这个两个对象各自的槽中。

当一个信号被发射出去,连接它的槽将立刻被执行,就像一个正常的函数调用。信号和槽机制是独立于任何GUI事件循环的。当所有的槽返回的时候,emit关键字也将返回。

如果几个槽和一个信号连接,当信号发射出去,按照一个任意的顺序,这些槽将一个一个的执行。

moc自动产生信号,信号没有被.cpp文件实现。信号没有返回值,(但可以使用void).

关于参数应该注意的是,我们的经验显示:如果我们不使用特别类型的函数,信号和槽是可以被重复 使用的。如果QScrollBar::valueChanged()使用了一个特别的类型,假定是QRangeControl::Range,那么它仅仅 只能和QRangeControl的槽连接。

槽:

当一个和槽相连接的信号被发射的时候,槽将被调用。槽是标准的c++函数,能够正常的被调用,他们唯一的特别之处就是他们和信号相连接。槽和信号不能够有实际的参数,it is rarely wise to use your own custom types for slot arguments.

由于槽只是一个带有一点点特别之处的标志的成员函数,他们也像正常的成员函数一样,有访问权限,一个槽的访问权限决定了谁可以和他连接。

一个public访问属性的槽可以和任何信号相连,这对于程序的构建是非常有用的。你建立的很多对象,他们之间没有什么联系,可以用槽和信号把他们联系在一起,,可以正确的传递消息,就像铁路标志,实现它,让它运行。

一个protected访问属性的槽可以和定义它的类,以及这个类的子类的信号相连接。这说明这个槽是定义它的类的一部分,而不是和外界打交道的接口。

一个privated的访问属性仅仅可以和定义它的类的信号相连接,这个类的子类的信号都不可以和这个槽相连接。

你可以把槽定义为虚函数,你将发现,这在实际中是非常有用的。

槽和信号机制是非常有效的,但并不像“实际”的callback函数那样快。信号和槽稍微有点慢,因为槽和信号增加了适应性,但这点问题是无关紧要的。通常来讲,一个和槽连接的发射中的信号,比程序直接调用它要慢十倍,



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

chinaunix网友2010-10-29 14:55:32

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com