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

📄 signalsandslots.html

📁 这是qt3的帮助文档的中文版
💻 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 + -