source: trunk/doc/html/tutorial2-08.html@ 203

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

reference documentation added

File size: 19.7 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:1017 -->
3<html>
4<head>
5<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
6<title>Taking Data</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>Taking Data</h1>
33
34
35<p>
36<p> <center><img src="chart-setdata.png" alt="The set data dialog"></center>
37<p> The set data dialog allows the user to add and edit values, and to
38choose the color and pattern used to display values. Users can also
39enter label text and choose a label color for each label.
40<p> (Extracts from <tt>setdataform.h</tt>.)
41<p>
42
43<pre> class SetDataForm: public <a href="qdialog.html">QDialog</a>
44 {
45 <a href="metaobjects.html#Q_OBJECT">Q_OBJECT</a>
46 public:
47 SetDataForm( ElementVector *elements, int decimalPlaces,
48 <a href="qwidget.html">QWidget</a> *parent = 0, const char *name = "set data form",
49 bool modal = TRUE, WFlags f = 0 );
50 ~SetDataForm() {}
51
52 public slots:
53 void setColor();
54 void setColor( int row, int col );
55 void currentChanged( int row, int col );
56 void valueChanged( int row, int col );
57
58 protected slots:
59 void accept();
60
61 private:
62 <a href="qtable.html">QTable</a> *table;
63 <a href="qpushbutton.html">QPushButton</a> *colorPushButton;
64 <a href="qpushbutton.html">QPushButton</a> *okPushButton;
65 <a href="qpushbutton.html">QPushButton</a> *cancelPushButton;
66
67 protected:
68 <a href="qvboxlayout.html">QVBoxLayout</a> *tableButtonBox;
69 <a href="qhboxlayout.html">QHBoxLayout</a> *buttonBox;
70
71 private:
72 ElementVector *m_elements;
73 int m_decimalPlaces;
74 };
75</pre>
76<p> The header file is simple. The constructor takes a pointer to the
77element vector so that this "smart" dialog can display and edit the
78data directly. We'll explain the slots as we look through the
79implementation.
80<p> (Extracts from <tt>setdataform.cpp</tt>.)
81<p>
82
83<pre> #include "images/pattern01.xpm"
84 #include "images/pattern02.xpm"
85</pre>
86<p> We have created a small <tt>.XPM</tt> image to show each brush pattern that
87Qt supports. We'll use these in the pattern combobox.
88<p> <h2> The Constructor
89</h2>
90<a name="1"></a><p> <pre> SetDataForm::SetDataForm( ElementVector *elements, int decimalPlaces,
91 <a href="qwidget.html">QWidget</a>* parent, const char* name,
92 bool modal, WFlags f )
93 : <a href="qdialog.html">QDialog</a>( parent, name, modal, f )
94
95 {
96 m_elements = elements;
97 m_decimalPlaces = decimalPlaces;
98</pre>
99<p> We pass most of the arguments to the <a href="qdialog.html">QDialog</a> superclass. We assign the
100elements vector pointer and the number of decimal places to display to
101member variables so that they are accessible by all SetDataForm's
102member functions.
103<p> <pre> <a href="qwidget.html#setCaption">setCaption</a>( "Chart -- Set Data" );
104 <a href="qwidget.html#resize">resize</a>( 540, 440 );
105</pre>
106<p> We set a caption for the dialog and resize it.
107<p> <pre> tableButtonBox = new <a href="qvboxlayout.html">QVBoxLayout</a>( this, 11, 6, "table button box layout" );
108</pre>
109<p> The layout of the form is quite simple. The buttons will be grouped
110together in a horizontal layout and the table and the button layout
111will be grouped together vertically using the tableButtonBox layout.
112<p> <pre> table = new <a href="qtable.html">QTable</a>( this, "data table" );
113 <a name="x2621"></a> table-&gt;<a href="qtable.html#setNumCols">setNumCols</a>( 5 );
114 <a name="x2622"></a> table-&gt;<a href="qtable.html#setNumRows">setNumRows</a>( ChartForm::MAX_ELEMENTS );
115 <a name="x2619"></a> table-&gt;<a href="qtable.html#setColumnReadOnly">setColumnReadOnly</a>( 1, TRUE );
116 table-&gt;<a href="qtable.html#setColumnReadOnly">setColumnReadOnly</a>( 2, TRUE );
117 table-&gt;<a href="qtable.html#setColumnReadOnly">setColumnReadOnly</a>( 4, TRUE );
118 <a name="x2620"></a> table-&gt;<a href="qtable.html#setColumnWidth">setColumnWidth</a>( 0, 80 );
119 table-&gt;<a href="qtable.html#setColumnWidth">setColumnWidth</a>( 1, 60 ); // Columns 1 and 4 must be equal
120 table-&gt;<a href="qtable.html#setColumnWidth">setColumnWidth</a>( 2, 60 );
121 table-&gt;<a href="qtable.html#setColumnWidth">setColumnWidth</a>( 3, 200 );
122 table-&gt;<a href="qtable.html#setColumnWidth">setColumnWidth</a>( 4, 60 );
123 <a name="x2616"></a> <a href="qheader.html">QHeader</a> *th = table-&gt;<a href="qtable.html#horizontalHeader">horizontalHeader</a>();
124 <a name="x2605"></a> th-&gt;<a href="qheader.html#setLabel">setLabel</a>( 0, "Value" );
125 th-&gt;<a href="qheader.html#setLabel">setLabel</a>( 1, "Color" );
126 th-&gt;<a href="qheader.html#setLabel">setLabel</a>( 2, "Pattern" );
127 th-&gt;<a href="qheader.html#setLabel">setLabel</a>( 3, "Label" );
128 th-&gt;<a href="qheader.html#setLabel">setLabel</a>( 4, "Color" );
129 tableButtonBox-&gt;<a href="qboxlayout.html#addWidget">addWidget</a>( table );
130</pre>
131<p> We create a new <a href="qtable.html">QTable</a> with five columns, and the same number of rows
132as we have elements in the elements vector. We make the color and
133pattern columns read only: this is to prevent the user typing in them.
134We will make the color changeable by the user clicking on a color or
135navigating to a color and clicking the Color button. The pattern will
136be in a combobox, changeable simply by the user selecting a different
137pattern. Next we set suitable initial widths, insert labels for each
138column and finally add the table to the tableButtonBox layout.
139<p> <pre> buttonBox = new <a href="qhboxlayout.html">QHBoxLayout</a>( 0, 0, 6, "button box layout" );
140</pre>
141<p> We create a horizontal box layout to hold the buttons.
142<p> <pre> colorPushButton = new <a href="qpushbutton.html">QPushButton</a>( this, "color button" );
143 <a name="x2598"></a> colorPushButton-&gt;<a href="qbutton.html#setText">setText</a>( "&amp;Color..." );
144 colorPushButton-&gt;<a href="qwidget.html#setEnabled">setEnabled</a>( FALSE );
145 buttonBox-&gt;<a href="qboxlayout.html#addWidget">addWidget</a>( colorPushButton );
146</pre>
147<p> We create a color button and add it to the buttonBox layout. We
148disable the button; we will only enable it when the focus is actually
149on a color cell.
150<p> <pre> <a href="qspaceritem.html">QSpacerItem</a> *spacer = new <a href="qspaceritem.html">QSpacerItem</a>( 0, 0, QSizePolicy::Expanding,
151 QSizePolicy::Minimum );
152 <a name="x2593"></a> buttonBox-&gt;<a href="qboxlayout.html#addItem">addItem</a>( spacer );
153</pre>
154<p> Since we want to separate the color button from the OK and Cancel
155buttons we next create a spacer and add that to the buttonBox layout.
156<p> <pre> okPushButton = new <a href="qpushbutton.html">QPushButton</a>( this, "ok button" );
157 okPushButton-&gt;<a href="qbutton.html#setText">setText</a>( "OK" );
158 <a name="x2607"></a> okPushButton-&gt;<a href="qpushbutton.html#setDefault">setDefault</a>( TRUE );
159 buttonBox-&gt;<a href="qboxlayout.html#addWidget">addWidget</a>( okPushButton );
160
161 cancelPushButton = new <a href="qpushbutton.html">QPushButton</a>( this, "cancel button" );
162 cancelPushButton-&gt;<a href="qbutton.html#setText">setText</a>( "Cancel" );
163 <a name="x2597"></a> cancelPushButton-&gt;<a href="qbutton.html#setAccel">setAccel</a>( Key_Escape );
164 buttonBox-&gt;<a href="qboxlayout.html#addWidget">addWidget</a>( cancelPushButton );
165</pre>
166<p> The OK and Cancel buttons are created and added to the buttonBox. We
167make the OK button the dialog's default button, and we make the <tt>Esc</tt>
168key an accelerator for the Cancel button.
169<p> <pre> <a name="x2594"></a> tableButtonBox-&gt;<a href="qboxlayout.html#addLayout">addLayout</a>( buttonBox );
170</pre>
171<p> We add the buttonBox layout to the tableButtonBox and the layout is
172complete.
173<p> <pre> <a name="x2612"></a> <a href="qobject.html#connect">connect</a>( table, SIGNAL( <a href="qtable.html#clicked">clicked</a>(int,int,int,const <a href="qpoint.html">QPoint</a>&amp;) ),
174 this, SLOT( setColor(int,int) ) );
175 <a name="x2613"></a> <a href="qobject.html#connect">connect</a>( table, SIGNAL( <a href="qtable.html#currentChanged">currentChanged</a>(int,int) ),
176 this, SLOT( currentChanged(int,int) ) );
177 <a name="x2626"></a> <a href="qobject.html#connect">connect</a>( table, SIGNAL( <a href="qtable.html#valueChanged">valueChanged</a>(int,int) ),
178 this, SLOT( valueChanged(int,int) ) );
179 <a name="x2596"></a> <a href="qobject.html#connect">connect</a>( colorPushButton, SIGNAL( <a href="qbutton.html#clicked">clicked</a>() ), this, SLOT( setColor() ) );
180 <a href="qobject.html#connect">connect</a>( okPushButton, SIGNAL( <a href="qbutton.html#clicked">clicked</a>() ), this, SLOT( <a href="qdialog.html#accept">accept</a>() ) );
181 <a href="qobject.html#connect">connect</a>( cancelPushButton, SIGNAL( <a href="qbutton.html#clicked">clicked</a>() ), this, SLOT( <a href="qdialog.html#reject">reject</a>() ) );
182</pre>
183<p> We now "wire up" the form.
184<ul>
185<li> If the user clicks a cell we call the setColor() slot; this will
186check that the cell is one that holds a color, and if it is, will
187invoke the color dialog.
188<li> We connect the <a href="qtable.html">QTable</a>'s currentChanged() signal to our own
189currentChanged() slot; this will be used to enable/disable the color
190button for example, depending on which column the user is in.
191<li> We connect the table's valueChanged() signal to our own
192valueChanged() slot; we'll use this to display the value with the
193correct number of decimal places.
194<li> If the user clicks the Color button we call a setColor() slot.
195<li> The OK button is connected to the accept() slot; we will update the
196elements vector in this slot.
197<li> The Cancel button is connected to the <a href="qdialog.html">QDialog</a> reject() slot, and
198requires no further code or action on our part.
199</ul>
200<p> <pre> QPixmap patterns[MAX_PATTERNS];
201 patterns[0] = QPixmap( pattern01 );
202 patterns[1] = QPixmap( pattern02 );
203</pre>
204<p> We create a pixmap for every brush pattern and store them in the <tt>patterns</tt> array.
205<p> <pre> <a name="x2610"></a> <a href="qrect.html">QRect</a> rect = table-&gt;<a href="qtable.html#cellRect">cellRect</a>( 0, 1 );
206 <a href="qpixmap.html">QPixmap</a> pix( rect.<a href="qrect.html#width">width</a>(), rect.<a href="qrect.html#height">height</a>() );
207</pre>
208<p> We obtain the rectangle that will be occupied by each color cell and
209create a blank pixmap of that size.
210<p> <pre> for ( int i = 0; i &lt; ChartForm::MAX_ELEMENTS; ++i ) {
211 Element element = (*m_elements)[i];
212
213 if ( element.isValid() )
214 table-&gt;<a href="qtable.html#setText">setText</a>(
215 i, 0,
216 QString( "%1" ).arg( element.value(), 0, 'f',
217 m_decimalPlaces ) );
218
219 <a href="qcolor.html">QColor</a> color = element.valueColor();
220 pix.<a href="qpixmap.html#fill">fill</a>( color );
221 table-&gt;<a href="qtable.html#setPixmap">setPixmap</a>( i, 1, pix );
222 table-&gt;<a href="qtable.html#setText">setText</a>( i, 1, color.<a href="qcolor.html#name">name</a>() );
223
224 <a href="qcombobox.html">QComboBox</a> *combobox = new <a href="qcombobox.html">QComboBox</a>;
225 for ( int j = 0; j &lt; MAX_PATTERNS; ++j )
226 combobox-&gt;<a href="qcombobox.html#insertItem">insertItem</a>( patterns[j] );
227 <a name="x2603"></a> combobox-&gt;<a href="qcombobox.html#setCurrentItem">setCurrentItem</a>( element.valuePattern() - 1 );
228 <a name="x2618"></a> table-&gt;<a href="qtable.html#setCellWidget">setCellWidget</a>( i, 2, combobox );
229
230 table-&gt;<a href="qtable.html#setText">setText</a>( i, 3, element.label() );
231
232 color = element.labelColor();
233 <a name="x2606"></a> pix.<a href="qpixmap.html#fill">fill</a>( color );
234 <a name="x2623"></a> table-&gt;<a href="qtable.html#setPixmap">setPixmap</a>( i, 4, pix );
235 <a name="x2624"></a><a name="x2600"></a> table-&gt;<a href="qtable.html#setText">setText</a>( i, 4, color.<a href="qcolor.html#name">name</a>() );
236</pre>
237<p> For each element in the element vector we must populate the table.
238<p> If the element is valid we write its value in the first column (column
2390, Value), formatting it with the specified number of decimal places.
240<p> We read the element's value color and fill the blank pixmap with that
241color; we then set the color cell to display this pixmap. We need to
242be able to read back the color later (e.g. if the user changes it).
243One way of doing this would be to examine a pixel in the pixmap;
244another way would be to subclass <a href="qtableitem.html">QTableItem</a> (in a similar way to our
245CanvasText subclass) and store the color there. But we've taken a
246simpler route: we set the cell's text to the name of the color.
247<p> Next we populate the pattern combobox with the patterns. We will use
248the position of the chosen pattern in the combobox to determine which
249pattern the user has selected. <a href="qtable.html">QTable</a> can make use of <a href="qcombotableitem.html">QComboTableItem</a>
250items; but these only support text, so we use setCellWidget() to
251insert <a href="qcombobox.html">QComboBox</a>'s into the table instead.
252<p> Next we insert the element's label. Finally we set the label color in
253the same way as we set the value color.
254<p> <h2> The Slots
255</h2>
256<a name="2"></a><p> <pre> void SetDataForm::currentChanged( int, int col )
257 {
258 colorPushButton-&gt;<a href="qwidget.html#setEnabled">setEnabled</a>( col == 1 || col == 4 );
259 }
260</pre>
261<p> As the user navigates through the table currentChanged() signals are
262emitted. If the user enters column 1 or 4 (value color or label color)
263we enable the colorPushButton; otherwise we disable it.
264<p> <pre> void SetDataForm::valueChanged( int row, int col )
265 {
266 if ( col == 0 ) {
267 bool ok;
268 <a name="x2625"></a> double d = table-&gt;<a href="qtable.html#text">text</a>( row, col ).toDouble( &amp;ok );
269 if ( ok &amp;&amp; d &gt; EPSILON )
270 table-&gt;<a href="qtable.html#setText">setText</a>(
271 row, col, QString( "%1" ).arg(
272 d, 0, 'f', m_decimalPlaces ) );
273 else if ( !table-&gt;<a href="qtable.html#text">text</a>( row, col ).isEmpty() )
274 table-&gt;<a href="qtable.html#setText">setText</a>( row, col, table-&gt;<a href="qtable.html#text">text</a>( row, col ) + "?" );
275 }
276 }
277</pre>
278<p> If the user changes the value we must format it using the correct
279number of decimal places, or indicate that it is invalid.
280<p> <pre> void SetDataForm::setColor()
281 {
282 <a name="x2615"></a><a name="x2614"></a> setColor( table-&gt;<a href="qtable.html#currentRow">currentRow</a>(), table-&gt;<a href="qtable.html#currentColumn">currentColumn</a>() );
283 table-&gt;<a href="qwidget.html#setFocus">setFocus</a>();
284 }
285</pre>
286<p> If the user presses the Color button we call the other setColor()
287function and put the focus back into the table.
288<p> <pre> void SetDataForm::setColor( int row, int col )
289 {
290 if ( !( col == 1 || col == 4 ) )
291 return;
292
293 <a name="x2601"></a> <a href="qcolor.html">QColor</a> color = QColorDialog::<a href="qcolordialog.html#getColor">getColor</a>(
294 QColor( table-&gt;<a href="qtable.html#text">text</a>( row, col ) ),
295 this, "color dialog" );
296 <a name="x2599"></a> if ( color.<a href="qcolor.html#isValid">isValid</a>() ) {
297 <a name="x2617"></a> <a href="qpixmap.html">QPixmap</a> pix = table-&gt;<a href="qtable.html#pixmap">pixmap</a>( row, col );
298 pix.<a href="qpixmap.html#fill">fill</a>( color );
299 table-&gt;<a href="qtable.html#setPixmap">setPixmap</a>( row, col, pix );
300 table-&gt;<a href="qtable.html#setText">setText</a>( row, col, color.<a href="qcolor.html#name">name</a>() );
301 }
302 }
303</pre>
304<p> If this function is called with the focus on a color cell we call
305the static <a href="qcolordialog.html#getColor">QColorDialog::getColor</a>() dialog to get the user's choice of
306color. If they chose a color we fill the color cell's pixmap with that
307color and set the cell's text to the new color's name.
308<p> <pre> <a name="x2604"></a>void SetDataForm::<a href="qdialog.html#accept">accept</a>()
309 {
310 bool ok;
311 for ( int i = 0; i &lt; ChartForm::MAX_ELEMENTS; ++i ) {
312 Element &amp;element = (*m_elements)[i];
313 double d = table-&gt;<a href="qtable.html#text">text</a>( i, 0 ).toDouble( &amp;ok );
314 if ( ok )
315 element.setValue( d );
316 else
317 element.setValue( Element::INVALID );
318 element.setValueColor( QColor( table-&gt;<a href="qtable.html#text">text</a>( i, 1 ) ) );
319 element.setValuePattern(
320 <a name="x2611"></a> ((QComboBox*)table-&gt;<a href="qtable.html#cellWidget">cellWidget</a>( i, 2 ))-&gt;currentItem() + 1 );
321 element.setLabel( table-&gt;<a href="qtable.html#text">text</a>( i, 3 ) );
322 element.setLabelColor( QColor( table-&gt;<a href="qtable.html#text">text</a>( i, 4 ) ) );
323 }
324
325 QDialog::<a href="qdialog.html#accept">accept</a>();
326 }
327</pre>
328<p> If the user clicks OK we must update the elements vector. We iterate
329over the vector and set each element's value to the value the user has
330entered or <tt>INVALID</tt> if the value is invalid. We set the value color
331and the label color by constructing <a href="qcolor.html">QColor</a> temporaries that take a
332color name as argument. The pattern is set to the pattern combobox's
333current item with an offset of 1 (since our pattern numbers begin at
3341, but the combobox's items are indexed from 0).
335<p> Finally we call <a href="qdialog.html#accept">QDialog::accept</a>().
336<p> <p align="right">
337<a href="tutorial2-07.html">&laquo; File Handling</a> |
338<a href="tutorial2.html">Contents</a> |
339<a href="tutorial2-09.html">Setting Options &raquo;</a>
340</p>
341<p>
342<!-- eof -->
343<p><address><hr><div align=center>
344<table width=100% cellspacing=0 border=0><tr>
345<td>Copyright &copy; 2007
346<a href="troll.html">Trolltech</a><td align=center><a href="trademarks.html">Trademarks</a>
347<td align=right><div align=right>Qt 3.3.8</div>
348</table></div></address></body>
349</html>
Note: See TracBrowser for help on using the repository browser.