?? tutorial1-07.html
字號:
<!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/tutorial.doc:670 -->
<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>Qt教程一 —— 第七章:一個事物領(lǐng)導(dǎo)另一個</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">函數(shù)</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>Qt教程一 —— 第七章:一個事物領(lǐng)導(dǎo)另一個</h1>
<p> <center><img src="t7.png" alt="Screenshot of tutorial seven"></center>
<p> 這個例子顯示了如何使用信號和槽來創(chuàng)建自定義窗口部件,和如何使用更加復(fù)雜的方式把它們連接起來。首先,源文件被我們分成幾部分并放在放在<tt>t7</tt>目錄下。
<p> <ul>
<li> <a href="t7-lcdrange-h.html">t7/lcdrange.h</a>包含LCDRange類定義。
<li> <a href="t7-lcdrange-cpp.html">t7/lcdrange.cpp</a>包含LCDRange類實(shí)現(xiàn)。
<li> <a href="t7-main-cpp.html">t7/main.cpp</a>包含MyWidget和main。
</ul>
<p> <h2> 一行一行地解說
</h2>
<a name="1"></a><p> <h3> <a href="t7-lcdrange-h.html">t7/lcdrange.h</a>
</h3>
<a name="1-1"></a><p> 這個文件主要利用了第六章的<a href="tutorial1-06.html#main">main.cpp</a>,在這里只是說明一下改變了哪些。
<p>
<p> <pre> #ifndef LCDRANGE_H
#define LCDRANGE_H
</pre>
<p> 這里是一個經(jīng)典的C語句,為了避免出現(xiàn)一個頭文件被包含不止一次的情況。如果你沒有使用過它,這是開發(fā)中的一個很好的習(xí)慣。#ifndef需要把這個頭文件的<em>全部</em>都包含進(jìn)去。
<p> <pre> #include <<a href="qvbox-h.html">qvbox.h</a>>
</pre>
<p> <a href="qvbox-h.html">qvbox.h</a>被包含了。LCDRange繼承了<a href="qvbox.html">QVBox</a>,所以父類的頭文件必須被包含。我們在前幾章里面偷了一點(diǎn)懶,我們通過包含其它一些頭文件,比如<a href="qpushbutton-h.html">qpushbutton.h</a>,這樣就可以間接地包含<a href="qwidget-h.html">qwidget.h</a>。
<p> <pre> class QSlider;
</pre>
<p> 這里是另外一個小伎倆,但是沒有前一個用的多。因?yàn)槲覀冊陬惖?lt;em>界面</em>中不需要<a href="qslider.html">QSlider</a>,僅僅是在實(shí)現(xiàn)中,我們在頭文件中使用一個前置的類聲明,并且在.cpp文件中包含一個QSlider的頭文件。
<p> 這會使編譯一個大的項(xiàng)目變得更快,因?yàn)楫?dāng)一個頭文件改變的時候,很少的文件需要重新編譯。它通常可以給大型編譯加速兩倍或兩倍以上。
<p> <pre> class LCDRange : public <a href="qvbox.html">QVBox</a>
{
<a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
public:
LCDRange( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );
</pre>
<p> <a href="metaobjects.html">meta object file</a>.
注意Q_OBJECT。這個宏必須被包含到<em>所有</em>使用信號和/或槽的類。如果你很好奇,它定義了在<a href="metaobjects.html">元對象文件</a>中實(shí)現(xiàn)的一些函數(shù)。
<p> <pre> int value() const;
public slots:
void setValue( int );
signals:
void valueChanged( int );
</pre>
<p> 這三個成員函數(shù)構(gòu)成了這個窗口部件和程序中其它組件的接口。直到現(xiàn)在,LCDRange根本沒有一個真正的接口。
<p> value()是一個可以訪問LCDRange的值的公共函數(shù)。setValue()是我們第一個自定義槽,并且valueChanged()是我們第一個自定義信號。
<p> 槽必須按通常的方式實(shí)現(xiàn)(記住槽也是一個C++成員函數(shù))。信號可以在<a href="signalsandslots.html">元對象</a>文件中自動實(shí)現(xiàn)。信號也遵守C++函數(shù)的保護(hù)法則(比如,一個類只能發(fā)射它自己定義的或者繼承來的信號)。
<p> 當(dāng)LCDRange的值發(fā)生變化時,valueChanged()信號就會被使用——你從這個名字中就可以猜到。這將不會是你將會看到的命名為<i>something</i>Changed()的最后一個信號。
<p> <h3> <a href="t7-lcdrange-cpp.html">t7/lcdrange.cpp</a>
</h3>
<a name="1-2"></a><p>
<p> 這個文件主要利用了<a href="tutorial1-06.html#main">t6/main.cpp</a>,在這里只是說明一下改變了哪些。
<p> <pre> <a name="x2265"></a> <a href="qobject.html#connect">connect</a>( slider, SIGNAL(<a href="qslider.html#valueChanged">valueChanged</a>(int)),
<a name="x2262"></a> lcd, SLOT(<a href="qlcdnumber.html#display">display</a>(int)) );
<a href="qobject.html#connect">connect</a>( slider, SIGNAL(<a href="qslider.html#valueChanged">valueChanged</a>(int)),
SIGNAL(valueChanged(int)) );
</pre>
<p> 這個代碼來自LCDRange的構(gòu)造函數(shù)。
<p> 第一個connect和你在上一章中看到的一樣。第二個是新的,它把滑塊的valueChanged()信號和這個對象的valueChanged<em>信號</em>連接起來了。帶有三個參數(shù)的connect()函數(shù)連接到<tt>this</tt>對象的信號或槽。
<p> 是的,這是正確的。信號可以被連接到其它的信號。當(dāng)?shù)谝粋€信號被發(fā)射時,第二個信號也被發(fā)射。
<p> 讓我們來看看當(dāng)用戶操作這個滑塊的時候都發(fā)生了些什么。滑塊看到自己的值發(fā)生了改變,并發(fā)射了valueChanged()信號。這個信號被連接到<a href="qlcdnumber.html">QLCDNumber</a>的display()槽和LCDRange的valueChanged()信號。
<p> 所以,當(dāng)這個信號被發(fā)射的時候,LCDRange發(fā)射它自己的valueChanged()信號。另外,<a href="qlcdnumber.html#display">QLCDNumber::display</a>()被調(diào)用并顯示新的數(shù)字。
<p> 注意你并沒有保證執(zhí)行的任何順序——LCDRange::valueChanged()也許在QLCDNumber::display()之前或者之后發(fā)射,這是完全任意的。
<p> <pre> int LCDRange::value() const
{
<a name="x2264"></a> return slider-><a href="qslider.html#value">value</a>();
}
</pre>
<p> value()的實(shí)現(xiàn)是直接了當(dāng)?shù)模唵蔚胤祷鼗瑝K的值。
<p> <pre> void LCDRange::setValue( int value )
{
<a name="x2263"></a> slider-><a href="qslider.html#setValue">setValue</a>( value );
}
</pre>
<p> setValue()的實(shí)現(xiàn)是相當(dāng)直接了當(dāng)?shù)摹W⒁庖驗(yàn)榛瑝K和LCD數(shù)字是連接的,設(shè)置滑塊的值就會自動的改變LCD數(shù)字的值。另外,如果滑塊的值超過了合法范圍,它會自動調(diào)節(jié)。
<p> <h3> <a href="t7-main-cpp.html">t7/main.cpp</a>
</h3>
<a name="1-3"></a><p>
<p> <pre> LCDRange *previous = 0;
for( int r = 0 ; r < 4 ; r++ ) {
for( int c = 0 ; c < 4 ; c++ ) {
LCDRange* lr = new LCDRange( grid );
if ( previous )
<a href="qobject.html#connect">connect</a>( lr, SIGNAL(valueChanged(int)),
previous, SLOT(setValue(int)) );
previous = lr;
}
}
</pre>
<p> main.cpp中所有的部分都是上一章復(fù)制的,除了MyWidget的構(gòu)造函數(shù)。當(dāng)我們創(chuàng)建16個RCDRange對象時,我們現(xiàn)在使用<a href="signalsandslots.html">信號/槽</a>機(jī)制連接它們。每一個的valueChanged()信號都和前一個的setValue()槽連接起來了。因?yàn)楫?dāng)LCDRange的值發(fā)生改變的時候,發(fā)射一個valueChanged()信號(驚奇!),我們在這里創(chuàng)建了一個信號和槽的“鏈”。
<p> <a name="compiling"></a>
<h2> 編譯
</h2>
<a name="2"></a><p> 為一個多文件的應(yīng)用程序創(chuàng)建一個makefile和為一個單文件的應(yīng)用程序創(chuàng)建一個makefile是沒有什么不同的。如果你已經(jīng)把這個例子中的所有文件都保存到它們自己的目錄中,你所要做的就是這些:
<pre>
qmake -project
qmake
</pre>
<p> 第一個命令調(diào)用<a href="qmake-manual.html">qmake</a>來生成一個<tt>.pro</tt>(項(xiàng)目)文件。第二個命令根據(jù)這個項(xiàng)目文件來生成一個(系統(tǒng)相關(guān)的)makefile。你現(xiàn)在可以輸入<tt>make</tt>(或者<tt>nmake</tt>,如果你使用Visual
Studio)。
<p> <h2> 行為
</h2>
<a name="3"></a><p> 在開始的時候,這個程序看起來和上一章里的一樣。試著操作滑塊到右下角……
<p> <h2> 練習(xí)
</h2>
<a name="4"></a><p> seven LCDs back to 50.
使用右下角的滑塊并設(shè)置所有的LCD到50。然后設(shè)置通過點(diǎn)擊這個滑塊的左側(cè)把它設(shè)置為40。現(xiàn)在,你可以通過把最后一個調(diào)到左邊來把前七個LCD設(shè)置回50。
<p> 點(diǎn)擊右下角滑塊的滑塊的左邊。發(fā)生了什么?為什么只是正確的行為?
<p> 現(xiàn)在你可以進(jìn)行<a href="tutorial1-08.html">第八章</a>了。
<p> [<a href="tutorial1-06.html">上一章</a>]
[<a href="tutorial1-08.html">下一章</a>]
[<a href="tutorial.html">教程一主頁</a>]
<p>
<!-- eof -->
<p><address><hr><div align=center>
<table width=100% cellspacing=0 border=0><tr>
<td>Copyright © 2002
<a href="http://www.trolltech.com">Trolltech</a>
<td><a href="http://www.trolltech.com/trademarks.html">Trademarks</a>
<td><a href="zh_CN.html">譯者:Cavendish</a>
<td align=right><div align=right>Qt 3.0.5版</div>
</table></div></address></body>
</html>
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -