source: trunk/doc/html/tutorial1-12.html@ 203

Last change on this file since 203 was 190, checked in by rudi, 14 years ago

reference documentation added

File size: 15.2 KB
Line 
1<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
2<!-- /home/espenr/tmp/qt-3.3.8-espenr-2499/qt-x11-free-3.3.8/doc/tutorial.doc:1711 -->
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Qt Tutorial - Chapter 12: Hanging in the Air the Way Bricks Don't</title>
7<style type="text/css"><!--
8fn { margin-left: 1cm; text-indent: -1cm; }
9a:link { color: #004faf; text-decoration: none }
10a:visited { color: #672967; text-decoration: none }
11body { background: #ffffff; color: black; }
12--></style>
13</head>
14<body>
15
16<table border="0" cellpadding="0" cellspacing="0" width="100%">
17<tr bgcolor="#E5E5E5">
18<td valign=center>
19 <a href="index.html">
20<font color="#004faf">Home</font></a>
21 | <a href="classes.html">
22<font color="#004faf">All&nbsp;Classes</font></a>
23 | <a href="mainclasses.html">
24<font color="#004faf">Main&nbsp;Classes</font></a>
25 | <a href="annotated.html">
26<font color="#004faf">Annotated</font></a>
27 | <a href="groups.html">
28<font color="#004faf">Grouped&nbsp;Classes</font></a>
29 | <a href="functions.html">
30<font color="#004faf">Functions</font></a>
31</td>
32<td align="right" valign="center"><img src="logo32.png" align="right" width="64" height="32" border="0"></td></tr></table><h1 align=center>Qt Tutorial - Chapter 12: Hanging in the Air the Way Bricks Don't</h1>
33
34
35<p> <center><img src="t12.png" alt="Screenshot of tutorial twelve"></center>
36<p> In this example, we extend our LCDRange class to include a text label.
37We also provide something to shoot at.
38<p> <ul>
39<li> <a href="t12-lcdrange-h.html">t12/lcdrange.h</a> contains the LCDRange
40class definition.
41<li> <a href="t12-lcdrange-cpp.html">t12/lcdrange.cpp</a> contains the LCDRange
42implementation.
43<li> <a href="t12-cannon-h.html">t12/cannon.h</a> contains the CannonField class
44definition.
45<li> <a href="t12-cannon-cpp.html">t12/cannon.cpp</a> contains the CannonField
46implementation.
47<li> <a href="t12-main-cpp.html">t12/main.cpp</a> contains MyWidget and main.
48</ul>
49<p> <h2> Line-by-line Walkthrough
50</h2>
51<a name="1"></a><p> <h3> <a href="t12-lcdrange-h.html">t12/lcdrange.h</a>
52</h3>
53<a name="1-1"></a><p> The LCDRange now has a text label.
54<p>
55
56<p> <pre> class QLabel;
57</pre>
58<p> We name declare <a href="qlabel.html">QLabel</a> because we want to use a pointer to it in the class
59definition.
60<p> <pre> class LCDRange : public <a href="qvbox.html">QVBox</a>
61 {
62 <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
63 public:
64 LCDRange( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );
65 LCDRange( const char *s, QWidget *parent=0,
66 const char *name=0 );
67</pre>
68<p> We have added a new constructor that sets the label text in addition to
69the parent and name.
70<p> <pre> const char *text() const;
71</pre>
72<p> This function returns the label text.
73<p> <pre> void setText( const char * );
74</pre>
75<p> This slot sets the label text.
76<p> <pre> private:
77 void init();
78</pre>
79<p> Because we now have two constructors, we have chosen to put the common
80initialization in the private init() function.
81<p> <pre> <a href="qlabel.html">QLabel</a> *label;
82</pre>
83<p> We also have a new private variable: a QLabel. QLabel is one of Qt's
84standard widgets and can show a text or a pixmap with or without a
85frame.
86<p> <h3> <a href="t12-lcdrange-cpp.html">t12/lcdrange.cpp</a>
87</h3>
88<a name="1-2"></a><p>
89
90<p> <pre> #include &lt;<a href="qlabel-h.html">qlabel.h</a>&gt;
91</pre>
92<p> Here we include the <a href="qlabel.html">QLabel</a> class definition.
93<p> <pre> LCDRange::LCDRange( <a href="qwidget.html">QWidget</a> *parent, const char *name )
94 : <a href="qvbox.html">QVBox</a>( parent, name )
95 {
96 init();
97 }
98</pre>
99<p> This constructor calls the init() function, which contains the common
100initialization code.
101<p> <pre> LCDRange::LCDRange( const char *s, QWidget *parent,
102 const char *name )
103 : <a href="qvbox.html">QVBox</a>( parent, name )
104 {
105 init();
106 setText( s );
107 }
108</pre>
109<p> This constructor first calls init() and then sets the label text.
110<p> <pre> void LCDRange::init()
111 {
112 <a href="qlcdnumber.html">QLCDNumber</a> *lcd = new <a href="qlcdnumber.html">QLCDNumber</a>( 2, this, "lcd" );
113 slider = new <a href="qslider.html">QSlider</a>( Horizontal, this, "slider" );
114 <a name="x2387"></a> slider-&gt;<a href="qrangecontrol.html#setRange">setRange</a>( 0, 99 );
115 <a name="x2388"></a> slider-&gt;<a href="qslider.html#setValue">setValue</a>( 0 );
116
117 label = new <a href="qlabel.html">QLabel</a>( " ", this, "label" );
118 <a name="x2383"></a> label-&gt;<a href="qlabel.html#setAlignment">setAlignment</a>( AlignCenter );
119
120 <a name="x2389"></a> <a href="qobject.html#connect">connect</a>( slider, SIGNAL(<a href="qslider.html#valueChanged">valueChanged</a>(int)),
121 <a name="x2386"></a> lcd, SLOT(<a href="qlcdnumber.html#display">display</a>(int)) );
122 <a href="qobject.html#connect">connect</a>( slider, SIGNAL(<a href="qslider.html#valueChanged">valueChanged</a>(int)),
123 SIGNAL(valueChanged(int)) );
124
125 <a href="qwidget.html#setFocusProxy">setFocusProxy</a>( slider );
126 }
127</pre>
128<p> The setup of <tt>lcd</tt> and <tt>slider</tt> is the same as in the previous
129chapter. Next we create a <a href="qlabel.html">QLabel</a> and tell it to align the contents
130centered (both vertically and horizontally). The connect() statements
131have also been taken from the previous chapter.
132<p> <pre> const char *LCDRange::text() const
133 {
134 <a name="x2385"></a> return label-&gt;<a href="qlabel.html#text">text</a>();
135 }
136</pre>
137<p> This function returns the label text.
138<p> <pre> void LCDRange::setText( const char *s )
139 {
140 <a name="x2384"></a> label-&gt;<a href="qlabel.html#setText">setText</a>( s );
141 }
142</pre>
143<p> This function sets the label text.
144<p> <h3> <a href="t12-cannon-h.html">t12/cannon.h</a>
145</h3>
146<a name="1-3"></a><p> The CannonField now has two new signals: hit() and missed(). In addition
147it contains a target.
148<p>
149
150<p> <pre> void newTarget();
151</pre>
152<p> This slot creates a target at a new position.
153<p> <pre> signals:
154 void hit();
155 void missed();
156</pre>
157<p> The hit() signal is emitted when a shot hits the target. The missed()
158signal is emitted when the shot moves beyond the right or bottom edge
159of the widget (i.e., it is certain that it has not and will not
160hit the target).
161<p> <pre> void paintTarget( <a href="qpainter.html">QPainter</a> * );
162</pre>
163<p> This private function paints the target.
164<p> <pre> <a href="qrect.html">QRect</a> targetRect() const;
165</pre>
166<p> This private function returns the enclosing rectangle of the target.
167<p> <pre> <a href="qpoint.html">QPoint</a> target;
168</pre>
169<p> This private variable contains the center point of the target.
170<p> <h3> <a href="t12-cannon-cpp.html">t12/cannon.cpp</a>
171</h3>
172<a name="1-4"></a><p>
173
174<p> <pre> #include &lt;<a href="qdatetime-h.html">qdatetime.h</a>&gt;
175</pre>
176<p> We include the <a href="qdate.html">QDate</a>, <a href="qtime.html">QTime</a>, and <a href="qdatetime.html">QDateTime</a> class definitions.
177<p> <pre> #include &lt;stdlib.h&gt;
178</pre>
179<p> We include the stdlib library because we need the rand() function.
180<p> <pre> newTarget();
181</pre>
182<p> This line has been added to the constructor. It creates a "random"
183position for the target. In fact, the newTarget() function will try
184to paint the target. Because we are in a constructor, the CannonField
185widget is invisible. Qt guarantees that no harm is done when calling
186repaint() on a hidden widget.
187<p> <pre> void CannonField::newTarget()
188 {
189 static bool first_time = TRUE;
190 if ( first_time ) {
191 first_time = FALSE;
192 <a href="qtime.html">QTime</a> midnight( 0, 0, 0 );
193 <a name="x2399"></a><a name="x2398"></a> srand( midnight.<a href="qtime.html#secsTo">secsTo</a>(QTime::<a href="qtime.html#currentTime">currentTime</a>()) );
194 }
195 <a href="qregion.html">QRegion</a> r( targetRect() );
196 target = QPoint( 200 + rand() % 190,
197 10 + rand() % 255 );
198 <a name="x2395"></a> <a href="qwidget.html#repaint">repaint</a>( r.<a href="qrect.html#unite">unite</a>( targetRect() ) );
199 }
200</pre>
201<p> This private function creates a target center point at a new "random"
202position.
203<p> We use the rand() function to fetch random integers. The rand() function
204normally returns the same series of numbers each time you run a program.
205This would make the target appear at the same position every time. To
206avoid this, we must set a random seed the first time this function is
207called. The random seed must also be random in order to avoid equal random
208number series. The solution is to use the number of seconds that have
209passed since midnight as a pseudo-random value.
210<p> First we create a static bool local variable. A static variable like
211this one is guaranteed to keep its value between calls to the function.
212<p> The <tt>if</tt> test will succeed only the first time this function is called
213because we set <tt>first_time</tt> to FALSE inside the <tt>if</tt> block.
214<p> Then we create the <a href="qtime.html">QTime</a> object <tt>midnight</tt>, which represents the time
21500:00:00. Next we fetch the number of seconds from midnight until
216now and use it as a random seed. See the documentation for <a href="qdate.html">QDate</a>,
217<a href="qtime.html">QTime</a>, and <a href="qdatetime.html">QDateTime</a> for more information.
218<p> Finally we calculate the target's center point. We keep it within
219the rectangle (x=200, y=35, width=190, height=255), (i.e., the
220possible x and y values are x = 200..389 and y = 35..289) in a
221coordinate system where we put y position 0 at the bottom edge of the
222widget and let y values increase upwards X is as normal, with 0 at
223the left edge and with x values increasing to the right.
224<p> By experimentation we have found this to always be in reach of the shot.
225<p> Note that rand() returns a random integer >= 0.
226<p> <pre> void CannonField::moveShot()
227 {
228 <a href="qregion.html">QRegion</a> r( shotRect() );
229 timerCount++;
230
231 <a href="qrect.html">QRect</a> shotR = shotRect();
232</pre>
233<p> This part of the timer event has not changed from the previous chapter.
234<p> <pre> if ( shotR.<a href="qrect.html#intersects">intersects</a>( targetRect() ) ) {
235 <a name="x2400"></a> autoShootTimer-&gt;<a href="qtimer.html#stop">stop</a>();
236 emit hit();
237</pre>
238<p> This <tt>if</tt> statement checks whether the shot rectangle intersects the
239target rectangle. If it does, the shot has hit the target (ouch!).
240We stop the shoot timer and emit the hit() signal to tell the outside
241world that a target was destroyed, and return.
242<p> Note that we could have created a new target on the spot, but because the
243CannonField is a component we leave such decisions to the user of the
244component.
245<p> <pre> <a name="x2397"></a><a name="x2396"></a> } else if ( shotR.<a href="qrect.html#x">x</a>() &gt; width() || shotR.<a href="qrect.html#y">y</a>() &gt; height() ) {
246 autoShootTimer-&gt;<a href="qtimer.html#stop">stop</a>();
247 emit missed();
248</pre>
249<p> This <tt>if</tt> statement is the same as in the previous chapter, except that
250it now emits the missed() signal to tell the outside world about the
251failure.
252<p> <pre> } else {
253</pre>
254<p> And the rest of the function is as before.
255<p> CannonField::paintEvent() is as before, except that this has been
256added:
257<p> <pre> <a name="x2393"></a> if ( updateR.<a href="qrect.html#intersects">intersects</a>( targetRect() ) )
258 paintTarget( &amp;p );
259</pre>
260<p> These two lines make sure that the target is also painted when necessary.
261<p> <pre> void CannonField::paintTarget( <a href="qpainter.html">QPainter</a> *p )
262 {
263 p-&gt;<a href="qpainter.html#setBrush">setBrush</a>( red );
264 p-&gt;<a href="qpainter.html#setPen">setPen</a>( black );
265 p-&gt;<a href="qpainter.html#drawRect">drawRect</a>( targetRect() );
266 }
267</pre>
268<p> This private function paints the target; a rectangle filled with red and
269with a black outline.
270<p> <pre> QRect CannonField::targetRect() const
271 {
272 <a href="qrect.html">QRect</a> r( 0, 0, 20, 10 );
273 <a name="x2394"></a> r.<a href="qrect.html#moveCenter">moveCenter</a>( QPoint(target.x(),height() - 1 - target.y()) );
274 return r;
275 }
276</pre>
277<p> This private function returns the enclosing rectangle of the target.
278Remember from newTarget() that the <tt>target</tt> point uses y coordinate 0 at
279the bottom of the widget. We calculate the point in widget coordinates
280before we call <a href="qrect.html#moveCenter">QRect::moveCenter</a>().
281<p> The reason we have chosen this coordinate mapping is to fix the distance
282between the target and the bottom of the widget. Remember that the widget
283can be resized by the user or the program at any time.
284<p> <h3> <a href="t12-main-cpp.html">t12/main.cpp</a>
285</h3>
286<a name="1-5"></a><p>
287
288<p> There are no new members in the MyWidget class, but we have slightly
289changed the constructor to set the new LCDRange text labels.
290<p> <pre> LCDRange *angle = new LCDRange( "ANGLE", this, "angle" );
291</pre>
292<p> We set the angle text label to "ANGLE".
293<p> <pre> LCDRange *force = new LCDRange( "FORCE", this, "force" );
294</pre>
295<p> We set the force text label to "FORCE".
296<p> <h2> Behavior
297</h2>
298<a name="2"></a><p> The LCDRange widgets look a bit strange - the built-in layout
299management in <a href="qvbox.html">QVBox</a> gives the labels too much space and the rest not
300enough. We'll fix that in the next chapter.
301<p> (See <a href="tutorial1-07.html#compiling">Compiling</a> for how to create a
302makefile and build the application.)
303<p> <h2> Exercises
304</h2>
305<a name="3"></a><p> Make a cheat button that, when pressed, makes the CannonField display
306the shot trajectory for five seconds.
307<p> If you did the "round shot" exercise from the previous chapter, try
308changing the shotRect() to a shotRegion() that returns a <a href="qregion.html">QRegion</a> so
309you can have really accurate collision detection.
310<p> Make a moving target.
311<p> Make sure that the target is always created entirely on-screen.
312<p> Make sure that the widget cannot be resized so that the target isn't
313visible. Hint: <a href="qwidget.html#setMinimumSize">QWidget::setMinimumSize</a>() is your friend.
314<p> Not easy; make it possible to have several shots in the air at the
315same time. Hint: make a Shot object.
316<p> You're now ready for <a href="tutorial1-13.html">Chapter 13.</a>
317<p> [<a href="tutorial1-11.html">Previous tutorial</a>]
318[<a href="tutorial1-13.html">Next tutorial</a>]
319[<a href="tutorial.html">Main tutorial page</a>]
320<p>
321<!-- eof -->
322<p><address><hr><div align=center>
323<table width=100% cellspacing=0 border=0><tr>
324<td>Copyright &copy; 2007
325<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
326<td align=right><div align=right>Qt 3.3.8</div>
327</table></div></address></body>
328</html>
Note: See TracBrowser for help on using the repository browser.