source: trunk/doc/html/tutorial2-03.html@ 190

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

reference documentation added

File size: 15.6 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/tutorial2.doc:110 -->
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Data Elements</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>Data Elements</h1>
33
34
35<p>
36<p> We will use a C++ class called <tt>Element</tt> to provide storage and
37access for data elements.
38<p> (Extracts from <tt>element.h</tt>.)
39<p>
40
41<pre> private:
42</pre><pre> double m_value;
43 <a href="qcolor.html">QColor</a> m_valueColor;
44 int m_valuePattern;
45 <a href="qstring.html">QString</a> m_label;
46 <a href="qcolor.html">QColor</a> m_labelColor;
47 double m_propoints[2 * MAX_PROPOINTS];
48</pre>
49<p> Each element has a value. Each value is displayed graphically with a
50particular color and fill pattern. Values may have a label associated
51with them; the label is drawn using the label color and for each type
52of chart has a (relative) position stored in the <tt>m_propoints</tt> array.
53<p>
54
55<pre> #include &lt;<a href="qcolor-h.html">qcolor.h</a>&gt;
56 #include &lt;<a href="qnamespace-h.html">qnamespace.h</a>&gt;
57 #include &lt;<a href="qstring-h.html">qstring.h</a>&gt;
58 #include &lt;<a href="qvaluevector-h.html">qvaluevector.h</a>&gt;
59</pre>
60<p> Although the <tt>Element</tt> class is a purely internal data class, it
61<tt>#include</tt>s four Qt classes. Qt is often perceived as a purely GUI
62toolkit, but it provides many non-GUI classes to support most aspects
63of application programming. We use <a href="qcolor-h.html">qcolor.h</a> so that we can hold the
64paint color and text color in the <tt>Element</tt> class. The use of <a href="qnamespace-h.html">qnamespace.h</a> is slightly obscure. Most Qt classes are derived from the
65<a href="qt.html">Qt</a> superclass which contains various
66enumerations. The <tt>Element</tt> class does not derive from <a href="qt.html">Qt</a>, so we need to include <a href="qnamespace-h.html">qnamespace.h</a> to have access to
67the Qt enum names. An alternative approach would have been to have
68made <tt>Element</tt> a <a href="qt.html">Qt</a> subclass. We include <a href="qstring-h.html">qstring.h</a> to make use of Qt's Unicode strings. As a convenience we
69will <tt>typedef</tt> a vector container for <tt>Element</tt>s, which is why we
70pull in the <a href="qvaluevector-h.html">qvaluevector.h</a> header.
71<p> <pre> typedef QValueVector&lt;Element&gt; ElementVector;
72</pre>
73<p> Qt provides a number of containers, some value based like
74<a href="qvaluevector.html">QValueVector</a>, and others pointer based. (See <a href="collection.html">Collection Classes</a>.) Here we've just typedefed one container
75type; we will keep each data set of elements in one <tt>ElementVector</tt>.
76<p> <pre> const double EPSILON = 0.0000001; // Must be &gt; INVALID.
77</pre>
78<p> Elements may only have positive values. Because we hold values as
79doubles we cannot readily compare them with zero. Instead we specify a
80value, <tt>EPSILON</tt>, which is close to zero, and consider any value
81greater than <tt>EPSILON</tt> to be positive and valid.
82<p> <pre> class Element
83 {
84 public:
85 enum { INVALID = -1 };
86 enum { NO_PROPORTION = -1 };
87 enum { MAX_PROPOINTS = 3 }; // One proportional point per chart type
88</pre>
89<p> We define three public enums for <tt>Element</tt>s. <tt>INVALID</tt> is used by
90the isValid() function. It is useful because we are going to use a
91fixed size vector of <tt>Element</tt>s, and can mark unused <tt>Element</tt>s by
92giving them <tt>INVALID</tt> values. The <tt>NO_PROPORTION</tt> enum is used to
93signify that the user has not positioned the Element's label; any
94positive proportion value is taken to be the text element's position
95proportional to the canvas's size.
96<p> If we stored each label's actual x and y position, then every time the
97user resized the main window (and therefore the canvas), the text
98would retain its original (now incorrect) position. So instead of
99storing absolute (x, y) positions we store <em>proportional</em> positions,
100i.e. x/width and y/height. We can then multiply these positions by
101the current width and height respectively when we come to draw the
102text and the text will be positioned correctly regardless of any
103resizing. For example, if a label has an x position of 300 and the
104canvas is 400 pixels wide, the proportional x value is 300/400 = 0.75.
105<p> The <tt>MAX_PROPOINTS</tt> enum is problematic. We need to store the x and y
106proportions for the text label for every chart type. And we have
107chosen to store these proportions in a fixed-size array. Because of
108this we must specify the maximum number of proportion pairs needed.
109This value must be changed if we change the number of chart types,
110which means that the <tt>Element</tt> class is strongly coupled to the
111number of chart types provided by the <tt>ChartForm</tt> class. In a
112larger application we might have used a vector to store these points
113and dynamically resized it depending on how many chart types are
114available.
115<p> <pre> Element( double value = INVALID, QColor valueColor = Qt::gray,
116 int valuePattern = Qt::SolidPattern,
117 const <a href="qstring.html">QString</a>&amp; label = <a href="qstring.html#QString-null">QString::null</a>,
118 <a href="qcolor.html">QColor</a> labelColor = Qt::black ) {
119 init( value, valueColor, valuePattern, label, labelColor );
120 for ( int i = 0; i &lt; MAX_PROPOINTS * 2; ++i )
121 m_propoints[i] = NO_PROPORTION;
122 }
123</pre>
124<p> The constructor provides default values for all members of the <tt>Element</tt> class. New elements always have label text with no position.
125We use an init() function because we also provide a set() function
126which works like the constructor apart from leaving the proportional
127positions alone.
128<p> <pre> bool isValid() const { return m_value &gt; EPSILON; }
129</pre>
130<p> Since we are storing <tt>Element</tt>s in a fixed size vector we need to be
131able to check whether a particular element is valid (i.e. should be
132used in calculations and displayed) or not. This is easily achieved
133with the isValid() function.
134<p> (Extracts from <tt>element.cpp</tt>.)
135<p>
136
137<pre> double Element::proX( int index ) const
138 {
139 <a href="qapplication.html#Q_ASSERT">Q_ASSERT</a>(index &gt;= 0 &amp;&amp; index &lt; MAX_PROPOINTS);
140 return m_propoints[2 * index];
141 }
142</pre>
143<p> Getters and setters are provided for all the members of <tt>Element</tt>.
144The proX() and proY() getters and the setProX() and setProY() setters
145take an index which identifies the type of chart the proportional
146position applies to. This means that the user can have labels
147positioned separately for the same data set for a vertical bar chart,
148a horizontal bar chart and for a pie chart. Note also that we use the
149<tt>Q_ASSERT</tt> macro to provide pre-condition tests on the chart type
150index; (see <a href="debug.html">Debugging</a>).
151<p> <h2> Reading and Writing Data Elements
152</h2>
153<a name="1"></a><p> (Extracts from <tt>element.h</tt>.)
154<p>
155
156<pre> QTextStream &amp;operator&lt;&lt;( <a href="qtextstream.html">QTextStream</a>&amp;, const Element&amp; );
157 QTextStream &amp;operator&gt;&gt;( <a href="qtextstream.html">QTextStream</a>&amp;, Element&amp; );
158</pre>
159<p> To make our <tt>Element</tt> class more self-contained we provide overloads
160for the &lt;&lt; and &gt;&gt; operators so that <tt>Element</tt>s may be written to
161and read from text streams. We could just as easily have used binary
162streams, but using text makes it possible for users to manipulate
163their data using a text editor and makes it easier to generate and
164filter the data using a scripting language.
165<p> (Extracts from <tt>element.cpp</tt>.)
166<p>
167
168<pre> #include "element.h"
169
170 #include &lt;<a href="qstringlist-h.html">qstringlist.h</a>&gt;
171 #include &lt;<a href="qtextstream-h.html">qtextstream.h</a>&gt;
172</pre>
173<p> Our implementation of the operators requires the inclusion of <a href="qtextstream-h.html">qtextstream.h</a> and <a href="qstringlist-h.html">qstringlist.h</a>.
174<p> <pre> const char FIELD_SEP = ':';
175 const char PROPOINT_SEP = ';';
176 const char XY_SEP = ',';
177</pre>
178<p> The format we are using to store the data is colon separated fields
179and newline separated records. The proportional points are semi-colon
180separated, with their x, y pairs being comma separated. The field
181order is value, value color, value pattern, label color, label points,
182label text. For example:
183<pre>
18420:#ff0000:14:#000000:0.767033,0.412946;0,0.75;0,0:Red :with colons:!
18570:#00ffff:2:#ffff00:0.450549,0.198661;0.198516,0.125954;0,0.198473:Cyan
18635:#0000ff:8:#555500:0.10989,0.299107;0.397032,0.562977;0,0.396947:Blue
18755:#ffff00:1:#000080:0.0989011,0.625;0.595547,0.312977;0,0.59542:Yellow
18880:#ff00ff:1:#000000:0.518681,0.694196;0.794063,0;0,0.793893:Magenta or Violet
189</pre>
190
191<p> There's no problem having whitespace and field separators in label
192text due to the way we read <tt>Element</tt> data.
193<p> <pre> QTextStream &amp;operator&lt;&lt;( <a href="qtextstream.html">QTextStream</a> &amp;s, const Element &amp;element )
194 {
195 s &lt;&lt; element.value() &lt;&lt; FIELD_SEP
196 &lt;&lt; element.valueColor().name() &lt;&lt; FIELD_SEP
197 &lt;&lt; element.valuePattern() &lt;&lt; FIELD_SEP
198 &lt;&lt; element.labelColor().name() &lt;&lt; FIELD_SEP;
199
200 for ( int i = 0; i &lt; Element::MAX_PROPOINTS; ++i ) {
201 s &lt;&lt; element.proX( i ) &lt;&lt; XY_SEP &lt;&lt; element.proY( i );
202 s &lt;&lt; ( i == Element::MAX_PROPOINTS - 1 ? FIELD_SEP : PROPOINT_SEP );
203 }
204
205 s &lt;&lt; element.label() &lt;&lt; '\n';
206
207 return s;
208 }
209</pre>
210<p> Writing elements is straight-forward. Each member is written followed
211by a field separator. The points are written as comma separated (<tt>XY_SEP</tt>) x, y pairs, each pair separated by the <tt>PROPOINT_SEP</tt>
212separator. The final field is the label followed by a newline.
213<p> <pre> QTextStream &amp;operator&gt;&gt;( <a href="qtextstream.html">QTextStream</a> &amp;s, Element &amp;element )
214 {
215 <a name="x2553"></a> <a href="qstring.html">QString</a> data = s.<a href="qtextstream.html#readLine">readLine</a>();
216 element.setValue( Element::INVALID );
217
218 int errors = 0;
219 bool ok;
220
221 <a name="x2552"></a> <a href="qstringlist.html">QStringList</a> fields = QStringList::<a href="qstringlist.html#split">split</a>( FIELD_SEP, data );
222 <a name="x2555"></a> if ( fields.<a href="qvaluelist.html#count">count</a>() &gt;= 4 ) {
223 double value = fields[0].toDouble( &amp;ok );
224 if ( !ok )
225 errors++;
226 <a href="qcolor.html">QColor</a> valueColor = QColor( fields[1] );
227 <a name="x2550"></a> if ( !valueColor.<a href="qcolor.html#isValid">isValid</a>() )
228 errors++;
229 int valuePattern = fields[2].toInt( &amp;ok );
230 if ( !ok )
231 errors++;
232 <a href="qcolor.html">QColor</a> labelColor = QColor( fields[3] );
233 if ( !labelColor.<a href="qcolor.html#isValid">isValid</a>() )
234 errors++;
235 <a href="qstringlist.html">QStringList</a> propoints = QStringList::<a href="qstringlist.html#split">split</a>( PROPOINT_SEP, fields[4] );
236 <a name="x2551"></a> <a href="qstring.html">QString</a> label = data.<a href="qstring.html#section">section</a>( FIELD_SEP, 5 );
237
238 if ( !errors ) {
239 element.set( value, valueColor, valuePattern, label, labelColor );
240 int i = 0;
241 <a name="x2554"></a> for ( QStringList::iterator point = propoints.<a href="qvaluelist.html#begin">begin</a>();
242 <a name="x2556"></a> i &lt; Element::MAX_PROPOINTS &amp;&amp; point != propoints.<a href="qvaluelist.html#end">end</a>();
243 ++i, ++point ) {
244 errors = 0;
245 <a href="qstringlist.html">QStringList</a> xy = QStringList::<a href="qstringlist.html#split">split</a>( XY_SEP, *point );
246 double x = xy[0].toDouble( &amp;ok );
247 if ( !ok || x &lt;= 0.0 || x &gt;= 1.0 )
248 errors++;
249 double y = xy[1].toDouble( &amp;ok );
250 if ( !ok || y &lt;= 0.0 || y &gt;= 1.0 )
251 errors++;
252 if ( errors )
253 x = y = Element::NO_PROPORTION;
254 element.setProX( i, x );
255 element.setProY( i, y );
256 }
257 }
258 }
259
260 return s;
261 }
262</pre>
263<p> To read an element we read one record (i.e. one line). We break the
264data into fields using <a href="qstringlist.html#split">QStringList::split</a>(). Because it is possible
265that a label will contain <tt>FIELD_SEP</tt> characters we use
266<a href="qstring.html#section">QString::section</a>() to extract all the text from the last field to the
267end of the line. If there are enough fields and the value, colors and
268pattern data is valid we use <tt>Element::set()</tt> to write this data into
269the element; otherwise we leave the element <tt>INVALID</tt>. We then
270iterate through the points. If the x and y proportions are valid and
271in range we set them for the element. If one or both proportions is
272invalid they will hold the value zero; this is not suitable so we
273change invalid (and out-of-range) proportional point values to <tt>NO_PROPORTION</tt>.
274<p> Our <tt>Element</tt> class is now sufficient to store, manipulate, read and
275write element data. We have also created an element vector typedef for
276storing a collection of elements.
277<p> We are now ready to create <tt>main.cpp</tt> and the user interface through
278which our users will create, edit and visualise their data sets.
279<p> <center><table cellpadding="4" cellspacing="2" border="0">
280<tr bgcolor="#f0f0f0">
281<td valign="top">For more information on Qt's data streaming facilities see <a href="datastreamformat.html">QDataStream Operators' Formats</a>, and see
282the source code for any of the Qt classes mentioned that are similar
283to what you want to store.
284</table></center>
285<p> <p align="right">
286<a href="tutorial2-02.html">&laquo; The 'Big Picture'</a> |
287<a href="tutorial2.html">Contents</a> |
288<a href="tutorial2-04.html">Mainly Easy &raquo;</a>
289</p>
290<p>
291<!-- eof -->
292<p><address><hr><div align=center>
293<table width=100% cellspacing=0 border=0><tr>
294<td>Copyright &copy; 2007
295<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
296<td align=right><div align=right>Qt 3.3.8</div>
297</table></div></address></body>
298</html>
Note: See TracBrowser for help on using the repository browser.