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

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

reference documentation added

File size: 14.5 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:868 -->
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Qt Tutorial - Chapter 8: Preparing for Battle</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 8: Preparing for Battle</h1>
33
34
35<p> <center><img src="t8.png" alt="Screenshot of tutorial eight"></center>
36<p> In this example, we introduce the first custom widget that can paint
37itself. We also add a useful keyboard interface (with two lines of
38code).
39<p> <ul>
40<li> <a href="t8-lcdrange-h.html">t8/lcdrange.h</a> contains the LCDRange class definition.
41<li> <a href="t8-lcdrange-cpp.html">t8/lcdrange.cpp</a> contains the LCDRange implementation.
42<li> <a href="t8-cannon-h.html">t8/cannon.h</a> contains the CannonField class definition.
43<li> <a href="t8-cannon-cpp.html">t8/cannon.cpp</a> contains the CannonField implementation.
44<li> <a href="t8-main-cpp.html">t8/main.cpp</a> contains MyWidget and main.
45</ul>
46<p> <h2> Line-by-line Walkthrough
47</h2>
48<a name="1"></a><p> <h3> <a href="t8-lcdrange-h.html">t8/lcdrange.h</a>
49</h3>
50<a name="1-1"></a><p> This file is very similar to the lcdrange.h in Chapter 7. We have added
51one slot: setRange().
52<p>
53
54<p> <pre> void setRange( int minVal, int maxVal );
55</pre>
56<p> We now add the possibility of setting the range of the LCDRange.
57Until now, it has been fixed at 0..99.
58<p> <h3> <a href="t8-lcdrange-cpp.html">t8/lcdrange.cpp</a>
59</h3>
60<a name="1-2"></a><p>
61
62<p> There is a change to the constructor (we'll discuss that later).
63<p> <pre> void LCDRange::setRange( int minVal, int maxVal )
64 {
65 if ( minVal &lt; 0 || maxVal &gt; 99 || minVal &gt; maxVal ) {
66 <a href="qapplication.html#qWarning">qWarning</a>( "LCDRange::setRange(%d,%d)\n"
67 "\tRange must be 0..99\n"
68 "\tand minVal must not be greater than maxVal",
69 minVal, maxVal );
70 return;
71 }
72 <a name="x2334"></a> slider-&gt;<a href="qrangecontrol.html#setRange">setRange</a>( minVal, maxVal );
73 }
74</pre>
75<p> SetRange() sets the range of the slider in the LCDRange. Because we
76have set up the <a href="qlcdnumber.html">QLCDNumber</a> to always display two digits, we want to
77limit the possible range of <tt>minVal</tt> and <tt>maxVal</tt> to 0..99 to avoid
78overflow of the QLCDNumber. (We could have allowed values down to -9
79but chose not to.) If the arguments are illegal, we use Qt's
80<a href="qapplication.html#qWarning">qWarning</a>() function to issue a warning to the user and return
81immediately. qWarning() is a printf-like function that by default
82sends its output to <tt>stderr</tt>. If you want, you can install your own handler
83function using <a href="qapplication.html#qInstallMsgHandler">::qInstallMsgHandler</a>().
84<p> <h3> <a href="t8-cannon-h.html">t8/cannon.h</a>
85</h3>
86<a name="1-3"></a><p> CannonField is a new custom widget that knows how to display itself.
87<p>
88
89<p> <pre> class CannonField : public <a href="qwidget.html">QWidget</a>
90 {
91 <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
92 public:
93 CannonField( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );
94</pre>
95<p> CannonField inherits <a href="qwidget.html">QWidget</a>, and we use the same idiom as for LCDRange.
96<p> <pre> int angle() const { return ang; }
97 <a href="qsizepolicy.html">QSizePolicy</a> sizePolicy() const;
98
99 public slots:
100 void setAngle( int degrees );
101
102 signals:
103 void angleChanged( int );
104</pre>
105<p> For the time being, CannonField only contains an angle value for which we
106provide an interface using the same idiom as for value in LCDRange.
107<p> <pre> protected:
108 void paintEvent( <a href="qpaintevent.html">QPaintEvent</a> * );
109</pre>
110<p> This is the second of the many event handlers in QWidget that we
111encounter. This virtual function is called by Qt whenever a widget needs
112to update itself (i.e., paint the widget's surface).
113<p> <h3> <a href="t8-cannon-cpp.html">t8/cannon.cpp</a>
114</h3>
115<a name="1-4"></a><p>
116
117<p> <pre> CannonField::CannonField( <a href="qwidget.html">QWidget</a> *parent, const char *name )
118 : <a href="qwidget.html">QWidget</a>( parent, name )
119 {
120</pre>
121<p> Again, we use the same idiom as for LCDRange in the previous chapter.
122<p> <pre> ang = 45;
123 <a href="qwidget.html#setPalette">setPalette</a>( QPalette( QColor( 250, 250, 200) ) );
124 }
125</pre>
126<p> The constructor initializes the angle value to 45 degrees and sets a
127custom palette for this widget.
128<p> This palette uses the indicated color as background and picks other
129colors suitably. (For this widget only the background and text
130colors will actually be used.)
131<p> <pre> void CannonField::setAngle( int degrees )
132 {
133 if ( degrees &lt; 5 )
134 degrees = 5;
135 if ( degrees &gt; 70 )
136 degrees = 70;
137 if ( ang == degrees )
138 return;
139 ang = degrees;
140 <a href="qwidget.html#repaint">repaint</a>();
141 emit angleChanged( ang );
142 }
143</pre>
144<p> This function sets the angle value. We have chosen a legal range of
1455..70 and adjust the given number of degrees accordingly. We have
146chosen not to issue a warning if the new angle is out of range.
147<p> If the new angle equals the old one, we return immediately. It is
148important to only emit the signal angleChanged() when the angle <em>really</em> has changed.
149<p> Then we set the new angle value and repaint our widget. The <a href="qwidget.html#repaint">QWidget::repaint</a>() function clears the widget (usually filling it with
150its background color) and sends a paint event to the widget. This
151results in a call to the paint event function of the widget.
152<p> Finally, we emit the angleChanged() signal to tell the outside world
153that the angle has changed. The <tt>emit</tt> keyword is unique to Qt and
154not regular C++ syntax. In fact, it is a macro.
155<p> <pre> <a name="x2336"></a>void CannonField::<a href="qwidget.html#paintEvent">paintEvent</a>( <a href="qpaintevent.html">QPaintEvent</a> * )
156 {
157 <a href="qstring.html">QString</a> s = "Angle = " + QString::number( ang );
158 <a href="qpainter.html">QPainter</a> p( this );
159 <a name="x2335"></a> p.<a href="qpainter.html#drawText">drawText</a>( 200, 200, s );
160 }
161</pre>
162<p> This is our first attempt to write a paint event handler. The event
163argument contains a description of the paint event. <a href="qpaintevent.html">QPaintEvent</a>
164contains the region in the widget that must be updated. For the time
165being, we will be lazy and just paint everything.
166<p> Our code displays the angle value in the widget at a fixed position.
167First we create a <a href="qstring.html">QString</a> with some text and the angle; then we create
168a <a href="qpainter.html">QPainter</a> operating on this widget and use it to paint the string.
169We'll come back to QPainter later; it can do a great many things.
170<p> <h3> <a href="t8-main-cpp.html">t8/main.cpp</a>
171</h3>
172<a name="1-5"></a><p>
173
174<p> <pre> #include "cannon.h"
175</pre>
176<p> We include our new class.
177<p> <pre> class MyWidget: public <a href="qwidget.html">QWidget</a>
178 {
179 public:
180 MyWidget( <a href="qwidget.html">QWidget</a> *parent=0, const char *name=0 );
181 };
182</pre>
183<p> This time we include a single LCDRange and a CannonField in our top-level
184widget.
185<p> <pre> LCDRange *angle = new LCDRange( this, "angle" );
186</pre>
187<p> In the constructor, we create and set up our LCDRange.
188<p> <pre> angle-&gt;setRange( 5, 70 );
189</pre>
190<p> We set the LCDRange to accept ranges from 5 to 70 degrees.
191<p> <pre> CannonField *cannonField
192 = new CannonField( this, "cannonField" );
193</pre>
194<p> We create our CannonField.
195<p> <pre> <a href="qobject.html#connect">connect</a>( angle, SIGNAL(valueChanged(int)),
196 cannonField, SLOT(setAngle(int)) );
197 <a href="qobject.html#connect">connect</a>( cannonField, SIGNAL(angleChanged(int)),
198 angle, SLOT(setValue(int)) );
199</pre>
200<p> Here we connect the valueChanged() signal of the LCDRange to the
201setAngle() slot of the CannonField. This will update CannonField's angle
202value whenever the user operates the LCDRange. We also make the reverse
203connection so that changing the angle in the CannonField will update the
204LCDRange value. In our example we never change the angle of the
205CannonField directly; but by doing the last connect() we ensure that no
206future changes will disrupt the synchronization between those two values.
207<p> This illustrates the power of component programming and proper
208encapsulation.
209<p> Notice how important it is to emit the angleChanged() signal only when
210the angle actually changes. If both the LCDRange and the CannonField
211had omitted this check, the program would have entered an infinite
212loop upon the first change of one of the values.
213<p> <pre> <a href="qgridlayout.html">QGridLayout</a> *grid = new <a href="qgridlayout.html">QGridLayout</a>( this, 2, 2, 10 );
214 //2x2, 10 pixel border
215</pre>
216<p> So far we have used the no-assembly-required <a href="qvbox.html">QVBox</a> and <a href="qgrid.html">QGrid</a> widgets
217for geometry management. Now, however, we want to have a little more
218control over the layout, and we switch to the more powerful <a href="qgridlayout.html">QGridLayout</a>
219class. QGridLayout isn't a widget; it is a different class that can
220manage the children of <em>any</em> widget.
221<p> As the comment indicates, we create a two-by-two array with ten pixel
222borders. (The constructor for <a href="qgridlayout.html">QGridLayout</a> can be a little cryptic,
223so it's good to put in such comments.)
224<p> <pre> <a name="x2337"></a> grid-&gt;<a href="qgridlayout.html#addWidget">addWidget</a>( quit, 0, 0 );
225</pre>
226<p> We add the Quit button in the top-left cell of the grid: 0, 0.
227<p> <pre> grid-&gt;<a href="qgridlayout.html#addWidget">addWidget</a>( angle, 1, 0, Qt::AlignTop );
228</pre>
229<p> We put the angle LCDRange in the bottom-left cell, aligned to the top
230of its cell. (This alignment is one of the things QGridLayout allows
231but QGrid does not allow.)
232<p> <pre> grid-&gt;<a href="qgridlayout.html#addWidget">addWidget</a>( cannonField, 1, 1 );
233</pre>
234<p> We put the CannonField object in the bottom-right cell. (The top-
235right cell is empty.)
236<p> <pre> <a name="x2338"></a> grid-&gt;<a href="qgridlayout.html#setColStretch">setColStretch</a>( 1, 10 );
237</pre>
238<p> We tell <a href="qgridlayout.html">QGridLayout</a> that the right column (column 1) is stretchable.
239Because the left column isn't (it has <a href="layout.html#stretch-factor">stretch factor</a> 0, the default
240value), QGridLayout will try to let the left-hand widgets' sizes be
241unchanged and will resize just the CannonField when the MyWidget is
242resized.
243<p> <pre> angle-&gt;setValue( 60 );
244</pre>
245<p> We set an initial angle value. Note that this will trigger the
246connection from LCDRange to CannonField.
247<p> <pre> <a name="x2339"></a> angle-&gt;<a href="qwidget.html#setFocus">setFocus</a>();
248</pre>
249<p> Our last action is to set <tt>angle</tt> to have <a href="focus.html#keyboard-focus">keyboard focus</a> so that
250keyboard input will go to the LCDRange widget by default.
251<p> LCDRange does not contain any keyPressEvent(), so that would seem not
252to be terribly useful. However, its constructor just got a new line:
253<p>
254
255<pre> <a href="qwidget.html#setFocusProxy">setFocusProxy</a>( slider );
256</pre>
257<p> The LCDRange sets the slider to be its focus proxy. That means that
258when someone (the program or the user) wants to give the LCDRange
259keyboard focus, the slider should take care of it. <a href="qslider.html">QSlider</a> has a decent
260keyboard interface, so with just one line of code we've given LCDRange
261one.
262<p> <h2> Behavior
263</h2>
264<a name="2"></a><p> The keyboard now does something - the arrow keys, Home, End, PageUp
265and PageDown all do something vaguely sensible.
266<p> When the slider is operated, the CannonField displays the new angle
267value. Upon resizing, CannonField is given as much space as possible.
268<p> On Windows machines with an 8-bit display the new background color is
269dithered to death. The next chapter works around this.
270<p> (See <a href="tutorial1-07.html#compiling">Compiling</a> for how to create a
271makefile and build the application.)
272<p> <h2> Exercises
273</h2>
274<a name="3"></a><p> Try to resize the window. What happens if you make it really narrow
275or really squat?
276<p> If you remove the AlignTop, what happens to the LCDRange's position
277and size? Why?
278<p> If you give the left-hand column a non-zero stretch factor, what
279happens when you resize the window?
280<p> Leave out the setFocus() call. Which behavior do you prefer?
281<p> Try to change "Quit" to "&Quit" in the <a href="qbutton.html#setText">QButton::setText</a>() call. How
282does the button's look change? What happens if you press Alt+Q while
283the program's running? (It is Meta+Q on a few keyboards.)
284<p> Center the text in the CannonField.
285<p> You're now ready for <a href="tutorial1-09.html">Chapter 9.</a>
286<p> [<a href="tutorial1-07.html">Previous tutorial</a>]
287[<a href="tutorial1-09.html">Next tutorial</a>]
288[<a href="tutorial.html">Main tutorial page</a>]
289<p>
290<!-- eof -->
291<p><address><hr><div align=center>
292<table width=100% cellspacing=0 border=0><tr>
293<td>Copyright &copy; 2007
294<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
295<td align=right><div align=right>Qt 3.3.8</div>
296</table></div></address></body>
297</html>
Note: See TracBrowser for help on using the repository browser.