source: trunk/doc/html/tutorial1-14.html

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

reference documentation added

File size: 14.2 KB
RevLine 
[190]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:2381 -->
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Qt Tutorial - Chapter 14: Facing the Wall</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 14: Facing the Wall</h1>
33
34
35<p> <center><img src="t14.png" alt="Screenshot of tutorial fourteen"></center>
36<p> This is the final example: a complete game.
37<p> We add keyboard accelerators and introduce mouse events to CannonField. We
38put a frame around the CannonField and add a barrier (wall) to make the
39game more challenging.
40<p> <ul>
41<li> <a href="t14-lcdrange-h.html">t14/lcdrange.h</a> contains the LCDRange
42class definition.
43<li> <a href="t14-lcdrange-cpp.html">t14/lcdrange.cpp</a> contains the LCDRange
44implementation.
45<li> <a href="t14-cannon-h.html">t14/cannon.h</a> contains the CannonField class
46definition.
47<li> <a href="t14-cannon-cpp.html">t14/cannon.cpp</a> contains the CannonField
48implementation.
49<li> <a href="t14-gamebrd-h.html">t14/gamebrd.h</a> contains the GameBoard
50class definition.
51<li> <a href="t14-gamebrd-cpp.html">t14/gamebrd.cpp</a> contains the GameBoard
52implementation.
53<li> <a href="t14-main-cpp.html">t14/main.cpp</a> contains MyWidget and main.
54</ul>
55<p> <h2> Line-by-line Walkthrough
56</h2>
57<a name="1"></a><p> <h3> <a href="t14-cannon-h.html">t14/cannon.h</a>
58</h3>
59<a name="1-1"></a><p> The CannonField can now receive mouse events to make the user aim the
60barrel by clicking on it and dragging. CannonField also has a barrier
61wall.
62<p>
63
64<p> <pre> protected:
65 void paintEvent( <a href="qpaintevent.html">QPaintEvent</a> * );
66 void mousePressEvent( <a href="qmouseevent.html">QMouseEvent</a> * );
67 void mouseMoveEvent( <a href="qmouseevent.html">QMouseEvent</a> * );
68 void mouseReleaseEvent( <a href="qmouseevent.html">QMouseEvent</a> * );
69</pre>
70<p> In addition to the familiar event handlers, CannonField implements
71three mouse event handlers. The names say it all.
72<p> <pre> void paintBarrier( <a href="qpainter.html">QPainter</a> * );
73</pre>
74<p> This private function paints the barrier wall.
75<p> <pre> <a href="qrect.html">QRect</a> barrierRect() const;
76</pre>
77<p> This private function returns the enclosing rectangle of the barrier.
78<p> <pre> bool barrelHit( const <a href="qpoint.html">QPoint</a> &amp; ) const;
79</pre>
80<p> This private function checks if a point is inside the barrel of the cannon.
81<p> <pre> bool barrelPressed;
82</pre>
83<p> This private variable is TRUE if the user has pressed the mouse on the
84barrel and not released it.
85<p> <h3> <a href="t14-cannon-cpp.html">t14/cannon.cpp</a>
86</h3>
87<a name="1-2"></a><p>
88
89<p> <pre> barrelPressed = FALSE;
90</pre>
91<p> This line has been added to the constructor. Initially, the mouse is
92not pressed on the barrel.
93<p> <pre> <a name="x2429"></a> } else if ( shotR.<a href="qrect.html#x">x</a>() &gt; width() || shotR.<a href="qrect.html#y">y</a>() &gt; height() ||
94 shotR.<a href="qrect.html#intersects">intersects</a>(barrierRect()) ) {
95</pre>
96<p> Now that we have a barrier, there are three ways to miss. We test for
97the third, too.
98<p> <pre> void CannonField::<a href="qwidget.html#mousePressEvent">mousePressEvent</a>( <a href="qmouseevent.html">QMouseEvent</a> *e )
99 {
100 if ( e-&gt;<a href="qmouseevent.html#button">button</a>() != LeftButton )
101 return;
102 <a name="x2418"></a> if ( barrelHit( e-&gt;<a href="qmouseevent.html#pos">pos</a>() ) )
103 barrelPressed = TRUE;
104 }
105</pre>
106<p> This is a Qt event handler. It is called when the user presses a
107mouse button when the mouse cursor is over the widget.
108<p> If the event was not generated by the left mouse button, we return
109immediately. Otherwise, we check if the position of the mouse cursor
110is within the cannon's barrel. If it is, we set <tt>barrelPressed</tt> to
111TRUE.
112<p> Notice that the pos() function returns a point in the widget's
113coordinate system.
114<p> <pre> void CannonField::<a href="qwidget.html#mouseMoveEvent">mouseMoveEvent</a>( <a href="qmouseevent.html">QMouseEvent</a> *e )
115 {
116 if ( !barrelPressed )
117 return;
118 <a href="qpoint.html">QPoint</a> pnt = e-&gt;<a href="qmouseevent.html#pos">pos</a>();
119 <a name="x2424"></a> if ( pnt.<a href="qpoint.html#x">x</a>() &lt;= 0 )
120 <a name="x2422"></a> pnt.<a href="qpoint.html#setX">setX</a>( 1 );
121 <a name="x2425"></a> if ( pnt.<a href="qpoint.html#y">y</a>() &gt;= <a href="qwidget.html#height">height</a>() )
122 <a name="x2423"></a> pnt.<a href="qpoint.html#setY">setY</a>( <a href="qwidget.html#height">height</a>() - 1 );
123 double rad = atan(((double)<a href="qwidget.html#rect">rect</a>().bottom()-pnt.<a href="qpoint.html#y">y</a>())/pnt.<a href="qpoint.html#x">x</a>());
124 setAngle( qRound ( rad*180/3.14159265 ) );
125 }
126</pre>
127<p> This is another Qt event handler. It is called when the user already
128has pressed the mouse button inside this widget and then moves/drags
129the mouse. (You can make Qt send mouse move events even when no
130buttons are pressed. See <a href="qwidget.html#setMouseTracking">QWidget::setMouseTracking</a>().)
131<p> This handler repositions the cannon's barrel according to the position of
132the mouse cursor.
133<p> First, if the barrel is not pressed, we return. Next, we fetch the
134mouse cursor's position. If the mouse cursor is to the left or below
135the widget, we adjust the point to be inside the widget.
136<p> Then we calculate the angle between the bottom edge of the widget and
137the imaginary line between the bottom-left corner of the widget and
138the cursor position. Finally we set the cannon's angle to the new
139value converted to degrees.
140<p> Remember that setAngle() redraws the cannon.
141<p> <pre> <a name="x2432"></a>void CannonField::<a href="qwidget.html#mouseReleaseEvent">mouseReleaseEvent</a>( <a href="qmouseevent.html">QMouseEvent</a> *e )
142 {
143 <a name="x2417"></a> if ( e-&gt;<a href="qmouseevent.html#button">button</a>() == LeftButton )
144 barrelPressed = FALSE;
145 }
146</pre>
147<p> This Qt event handler is called whenever the user releases a mouse
148button and it was pressed inside this widget.
149<p> If the left button is released, we can be sure that the barrel is no
150longer pressed.
151<p> The paint event has two extra lines:
152<p> <pre> <a name="x2427"></a> if ( updateR.<a href="qrect.html#intersects">intersects</a>( barrierRect() ) )
153 paintBarrier( &amp;p );
154</pre>
155<p> paintBarrier() does the same sort of thing as paintShot(),
156paintTarget(), and paintCannon().
157<p> <pre> void CannonField::paintBarrier( <a href="qpainter.html">QPainter</a> *p )
158 {
159 p-&gt;<a href="qpainter.html#setBrush">setBrush</a>( yellow );
160 p-&gt;<a href="qpainter.html#setPen">setPen</a>( black );
161 p-&gt;<a href="qpainter.html#drawRect">drawRect</a>( barrierRect() );
162 }
163</pre>
164<p> This private function paints the barrier as a rectangle filled with
165yellow and with a black outline.
166<p> <pre> QRect CannonField::barrierRect() const
167 {
168 return QRect( 145, height() - 100, 15, 100 );
169 }
170</pre>
171<p> This private function returns the rectangle of the barrier. We fix
172the bottom edge of the barrier to the bottom edge of the widget.
173<p> <pre> bool CannonField::barrelHit( const <a href="qpoint.html">QPoint</a> &amp;p ) const
174 {
175 <a href="qwmatrix.html">QWMatrix</a> mtx;
176 <a name="x2436"></a> mtx.<a href="qwmatrix.html#translate">translate</a>( 0, height() - 1 );
177 <a name="x2435"></a> mtx.<a href="qwmatrix.html#rotate">rotate</a>( -ang );
178 <a name="x2433"></a> mtx = mtx.<a href="qwmatrix.html#invert">invert</a>();
179 <a name="x2434"></a><a name="x2426"></a> return barrelRect.<a href="qrect.html#contains">contains</a>( mtx.<a href="qwmatrix.html#map">map</a>(p) );
180 }
181</pre>
182<p> This function returns TRUE if the point is in the barrel; otherwise it returns
183FALSE.
184<p> Here we use the class <a href="qwmatrix.html">QWMatrix</a>. It is defined in the header file
185qwmatrix.h, which is included by qpainter.h.
186<p> <a href="qwmatrix.html">QWMatrix</a> defines a coordinate system mapping. It can perform the same
187transformations as the <a href="qpainter.html">QPainter</a>.
188<p> Here we perform the same transformation steps as we do when drawing
189the barrel in the paintCannon() function. First we translate the
190coordinate system and then we rotate it.
191<p> Now we need to check whether the point <tt>p</tt> (in widget coordinates) lies
192inside the barrel. To do this, we invert the <a href="qwmatrix.html#TransformationMode">transformation matrix</a>.
193The inverted matrix performs the inverse transformation that we used
194when drawing the barrel. We map the point <tt>p</tt> using the inverted
195matrix and return TRUE if it is inside the original barrel rectangle.
196<p> <h3> <a href="t14-gamebrd-cpp.html">t14/gamebrd.cpp</a>
197</h3>
198<a name="1-3"></a><p>
199
200<p> <pre> #include &lt;<a href="qaccel-h.html">qaccel.h</a>&gt;
201</pre>
202<p> We include the class definition of <a href="qaccel.html">QAccel</a>.
203<p> <pre> <a href="qvbox.html">QVBox</a> *box = new <a href="qvbox.html">QVBox</a>( this, "cannonFrame" );
204 box-&gt;<a href="qframe.html#setFrameStyle">setFrameStyle</a>( QFrame::WinPanel | QFrame::Sunken );
205 cannonField = new CannonField( box, "cannonField" );
206</pre>
207<p> We create and set up a <a href="qvbox.html">QVBox</a>, set its frame style, and then create
208<tt>CannonField</tt> as a child of that box. Because nothing else is in the
209box, the effect is that the <a href="qvbox.html">QVBox</a> will put a frame around the
210CannonField.
211<p> <pre> <a href="qaccel.html">QAccel</a> *accel = new <a href="qaccel.html">QAccel</a>( this );
212 <a name="x2438"></a><a name="x2437"></a> accel-&gt;<a href="qaccel.html#connectItem">connectItem</a>( accel-&gt;<a href="qaccel.html#insertItem">insertItem</a>( Key_Enter ),
213 this, SLOT(fire()) );
214 accel-&gt;<a href="qaccel.html#connectItem">connectItem</a>( accel-&gt;<a href="qaccel.html#insertItem">insertItem</a>( Key_Return ),
215 this, SLOT(fire()) );
216</pre>
217<p> Here we create and set up an accelerator. An accelerator is an object
218that intercepts keyboard events to an application and calls slots if
219certain keys are pressed. This mechanism is also called shortcut
220keys. Note that an accelerator is a child of a widget and will be
221destroyed when that widget is destroyed. <a href="qaccel.html">QAccel</a> is <em>not</em> a widget
222and has no visible effect on its parent.
223<p> We define two shortcut keys. We want the slot fire() to be called
224when the user presses Enter, and we want the application to quit when
225key Ctrl+Q is pressed. Because Enter is sometimes Return and there
226are even keyboards with <em>both</em> keys, we make both Enter and Return
227invoke fire().
228<p> <pre> accel-&gt;<a href="qaccel.html#connectItem">connectItem</a>( accel-&gt;<a href="qaccel.html#insertItem">insertItem</a>( CTRL+Key_Q ),
229 qApp, SLOT(<a href="qapplication.html#quit">quit</a>()) );
230</pre>
231<p> And then we set up Ctrl+Q to do the same thing as Alt+Q. Some
232people are more used to Ctrl+Q (and anyway it shows how do do it).
233<p> CTRL, Key_Enter, Key_Return and Key_Q are all constants provided by
234Qt. They're actually Qt::Key_Enter, etc., but practically all classes
235inherit the <a href="qt.html">Qt</a> namespace class.
236<p> <pre> <a href="qgridlayout.html">QGridLayout</a> *grid = new <a href="qgridlayout.html">QGridLayout</a>( this, 2, 2, 10 );
237 <a name="x2441"></a> grid-&gt;<a href="qgridlayout.html#addWidget">addWidget</a>( quit, 0, 0 );
238 grid-&gt;<a href="qgridlayout.html#addWidget">addWidget</a>( box, 1, 1 );
239 <a name="x2442"></a> grid-&gt;<a href="qgridlayout.html#setColStretch">setColStretch</a>( 1, 10 );
240</pre>
241<p> We put <tt>box</tt> (the <a href="qvbox.html">QVBox</a>), not the CannonField, in the lower-right
242cell.
243<p> <h2> Behavior
244</h2>
245<a name="2"></a><p> The cannon now shoots when you press Enter. You can also position the
246cannon's angle using the mouse. The barrier makes it a little more
247challenging to play the game. We also have a nice looking frame
248around the CannonField.
249<p> (See <a href="tutorial1-07.html#compiling">Compiling</a> for how to create a
250makefile and build the application.)
251<p> <h2> Exercises
252</h2>
253<a name="3"></a><p> Write a space invaders game.
254<p> (This exercise was first done by
255<a href="mailto:igorr@ifi.uio.no">Igor Rafienko</a>. You can
256<a href="http://www.stud.ifi.uio.no/~igorr/download.html">download his game</a>.)
257<p> The new exercise is: Write a Breakout game.
258<p> Final exhortation: Go forth now and create <em>masterpieces of the programming art!</em>
259<p>
260<p> [<a href="tutorial1-13.html">Previous tutorial</a>]
261[<a href="tutorial1-01.html">First tutorial</a>]
262[<a href="tutorial.html">Main tutorial page</a>]
263<p>
264<!-- eof -->
265<p><address><hr><div align=center>
266<table width=100% cellspacing=0 border=0><tr>
267<td>Copyright &copy; 2007
268<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
269<td align=right><div align=right>Qt 3.3.8</div>
270</table></div></address></body>
271</html>
Note: See TracBrowser for help on using the repository browser.