⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 signalsandslots.html

📁 QT 下载资料仅供参考
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"><!-- /home/reggie/tmp/qt-3.0-reggie-5401/qt-win-commercial-3.0.5/doc/signalsandslots.doc:36 --><html><head><meta http-equiv="Content-Type" content="text/html; charset=gb2312"><meta name="Translator" content="Cavendish"><meta name="Qt zh_CN Documents Website" content="http://www.qiliang.net/qt"><title>信号和槽</title><style type="text/css"><!--h3.fn,span.fn { margin-left: 1cm; text-indent: -1cm; }a:link { color: #004faf; text-decoration: none }a:visited { color: #672967; text-decoration: none }body { background: #ffffff; color: black; font-family: "Times New Roman" }--></style></head><body><table border="0" cellpadding="0" cellspacing="0" width="100%"><tr bgcolor="#E5E5E5"><td valign=center> <a href="index.html"><font color="#004faf">主页</font></a> | <a href="classes.html"><font color="#004faf">所有的类</font></a> | <a href="mainclasses.html"><font color="#004faf">主要的类</font></a> | <a href="annotated.html"><font color="#004faf">注释的类</font></a> | <a href="groups.html"><font color="#004faf">分组的类</font></a> | <a href="functions.html"><font color="#004faf">函数</font></a></td><td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>信号和槽</h1> <p> 信号和槽用于对象间的通讯。信号/槽机制是Qt的一个中心特征并且也许是Qt与其它工具包的最不相同的部分。<p> 在图形用户界面编程中,我们经常希望一个窗口部件的一个变化被通知给另一个窗口部件。更一般地,我们希望任何一类的对象可以和其它对象进行通讯。例如,如果我们正在解析一个XML文件,当我们遇到一个新的标签时,我们也许希望通知列表视图我们正在用来表达XML文件的结构。<p> 较老的工具包使用一种被称作回调的通讯方式来实现同一目的。回调是指一个函数的指针,所以如果你希望一个处理函数通知你一些事件,你可以把另一个函数(回调)的指针传递给处理函数。处理函数在适当的时候调用回调。回调有两个主要缺点。首先他们不是类型安全的。我们从来都不能确定处理函数使用了正确的参数来调用回调。其次回调和处理函数是非常强有力地联系在一起的,因为处理函数必须知道要调用哪个回调。<p> <center><img src="abstract-connections.png"></center> <blockquote><p align="center"><em> 一个关于一些信号和槽连接的摘要图</em></p></blockquote><p> 在Qt中我们有一种可以替代回调的技术。我们使用信号和槽。当一个特定事件发生的时候,一个信号被发射。Qt的窗口部件有很多预定义的信号,但是我们总是可以通过继承来加入我们自己的信号。槽就是一个可以被调用处理特定信号的函数。Qt的窗口部件又很多预定义的槽,但是通常的习惯是你可以加入自己的槽,这样你就可以处理你所感兴趣的信号。<p> 信号和槽的机制是类型安全的:一个信号的签名必须与它的接收槽的签名相匹配。(实际上一个槽的签名可以比它接收的信号的签名少,因为它可以忽略额外的签名。)因为签名是一致的,编译器就可以帮助我们检测类型不匹配。信号和槽是宽松地联系在一起的:一个发射信号的类不用知道也不用注意哪个槽要接收这个信号。Qt的信号和槽的机制可以保证如果你把一个信号和一个槽连接起来,槽会在正确的时间使用信号的参数而被调用。信号和槽可以使用任何数量、任何类型的参数。它们是完全类型安全的:不会再有回调核心转储(core dump)。<p> 从<a href="qobject.html">QObject</a>类或者它的一个子类(比如<a href="qwidget.html">QWidget</a>类)继承的所有类可以包含信号和槽。当对象改变它们的状态的时候,信号被发送,从某种意义上讲,它们也许对外面的世界感兴趣。这就是所有的对象通讯时所做的一切。它不知道也不注意无论有没有东西接收它所发射的信号。这就是真正的信息封装,并且确保对象可以用作一个软件组件。<p> <center><img src="concrete-connections.png"></center> <blockquote><p align="center"><em> 一个信号和槽连接的例子</em></p></blockquote><p> 槽可以用来接收信号,但它们是正常的成员函数。一个槽不知道它是否被任意信号连接。此外,对象不知道关于这种通讯机制和能够被用作一个真正的软件组件。<p> 你可以把许多信号和你所希望的单一槽相连,并且一个信号也可以和你所期望的许多槽相连。把一个信号和另一个信号直接相连也是可以的。(这时,只要第一个信号被发射时,第二个信号立刻就被发射。)<p> 总体来看,信号和槽构成了一个强有力的组件编程机制。<p> <h2> 一个小例子</h2><a name="1"></a><p> 一个最小的C++类声明如下:<p> <pre>    class Foo    {    public:        Foo();        int value() const { return val; }        void setValue( int );    private:        int val;    };</pre> <p> 一个小的Qt类如下:<p> <pre>    class Foo : public <a href="qobject.html">QObject</a>    {        <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>    public:        Foo();        int value() const { return val; }    public slots:        void setValue( int );    signals:        void valueChanged( int );    private:        int val;    };</pre> <p> 这个类有同样的内部状态,和公有方法来访问状态,但是另外它也支持使用信号和槽的组件编程:这个类可以通过发射一个信号,<tt>valueChanged()</tt>,来告诉外面的世界它的状态发生了变化,并且它有一个槽,其它对象可以发送信号给这个槽。<p> 所有包含信号和/或者槽的类必须在它们的声明中提到Q_OBJECT。<p> 槽可以由应用程序的编写者来实现。这里是Foo::setValue()的一个可能的实现:<p> <pre>    void Foo::setValue( int v )    {        if ( v != val ) {            val = v;            emit valueChanged(v);        }    }</pre> <p> <tt>emit valueChanged(v)</tt>这一行从对象中发射<tt>valueChanged</tt>信号。正如你所能看到的,你通过使用<tt>emit signal(arguments)</tt>来发射信号。<p> 下面是把两个对象连接在一起的一种方法:<p> <pre>    Foo a, b;    connect(&amp;a, SIGNAL(valueChanged(int)), &amp;b, SLOT(setValue(int)));    b.setValue( 11 ); // a == undefined  b == 11    a.setValue( 79 ); // a == 79         b == 79    b.value();        </pre> <p> 调用<tt>a.setValue(79)</tt>会使<tt>a</tt>发射一个<tt>valueChanged()</tt>信号,<tt>b</tt>将会在它的<tt>setValue()</tt>槽中接收这个信号,也就是<tt>b.setValue(79)</tt>被调用。接下来<tt>b</tt>会发射同样的<tt>valueChanged()</tt>信号,但是因为没有槽被连接到<tt>b</tt>的<tt>valueChanged()</tt>信号,所以没有发生任何事(信号消失了)。<p> 注意只有当<tt>v != val</tt>的时候<tt>setValue()</tt>函数才会设置这个值并且发射信号。这样就避免了在循环连接的情况下(比如<tt>b.valueChanged()</tt>和<tt>a.setValue()</tt>连接在一起)出现无休止的循环的情况。

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -