source: trunk/doc/src/examples/calculator.qdoc

Last change on this file was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 16.6 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation (qt-info@nokia.com)
6**
7** This file is part of the documentation of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:FDL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in a
14** written agreement between you and Nokia.
15**
16** GNU Free Documentation License
17** Alternatively, this file may be used under the terms of the GNU Free
18** Documentation License version 1.3 as published by the Free Software
19** Foundation and appearing in the file included in the packaging of this
20** file.
21**
22** If you have questions regarding the use of this file, please contact
23** Nokia at qt-info@nokia.com.
24** $QT_END_LICENSE$
25**
26****************************************************************************/
27
28/*!
29 \example widgets/calculator
30 \title Calculator Example
31
32 The example shows how to use signals and slots to implement the
33 functionality of a calculator widget, and how to use QGridLayout
34 to place child widgets in a grid.
35
36 \image calculator-example.png Screenshot of the Calculator example
37
38 The example consists of two classes:
39
40 \list
41 \o \c Calculator is the calculator widget, with all the
42 calculator functionality.
43 \o \c Button is the widget used for each of the calculator
44 button. It derives from QToolButton.
45 \endlist
46
47 We will start by reviewing \c Calculator, then we will take a
48 look at \c Button.
49
50 \section1 Calculator Class Definition
51
52 \snippet examples/widgets/calculator/calculator.h 0
53
54 The \c Calculator class provides a simple calculator widget. It
55 inherits from QDialog and has several private slots associated
56 with the calculator's buttons. QObject::eventFilter() is
57 reimplemented to handle mouse events on the calculator's display.
58
59 Buttons are grouped in categories according to their behavior.
60 For example, all the digit buttons (labeled \gui 0 to \gui 9)
61 append a digit to the current operand. For these, we connect
62 multiple buttons to the same slot (e.g., \c digitClicked()). The
63 categories are digits, unary operators (\gui{Sqrt}, \gui{x\unicode{178}},
64 \gui{1/x}), additive operators (\gui{+}, \gui{-}), and
65 multiplicative operators (\gui{\unicode{215}}, \gui{\unicode{247}}). The other buttons
66 have their own slots.
67
68 \snippet examples/widgets/calculator/calculator.h 1
69 \snippet examples/widgets/calculator/calculator.h 2
70
71 The private \c createButton() function is used as part of the
72 widget construction. \c abortOperation() is called whenever a
73 division by zero occurs or when a square root operation is
74 applied to a negative number. \c calculate() applies a binary
75 operator (\gui{+}, \gui{-}, \gui{\unicode{215}}, or \gui{\unicode{247}}).
76
77 \snippet examples/widgets/calculator/calculator.h 3
78 \snippet examples/widgets/calculator/calculator.h 4
79 \snippet examples/widgets/calculator/calculator.h 5
80 \snippet examples/widgets/calculator/calculator.h 6
81 \snippet examples/widgets/calculator/calculator.h 7
82 \snippet examples/widgets/calculator/calculator.h 8
83
84 These variables, together with the contents of the calculator
85 display (a QLineEdit), encode the state of the calculator:
86
87 \list
88 \o \c sumInMemory contains the value stored in the calculator's memory
89 (using \gui{MS}, \gui{M+}, or \gui{MC}).
90 \o \c sumSoFar stores the value accumulated so far. When the user
91 clicks \gui{=}, \c sumSoFar is recomputed and shown on the
92 display. \gui{Clear All} resets \c sumSoFar to zero.
93 \o \c factorSoFar stores a temporary value when doing
94 multiplications and divisions.
95 \o \c pendingAdditiveOperator stores the last additive operator
96 clicked by the user.
97 \o \c pendingMultiplicativeOperator stores the last multiplicative operator
98 clicked by the user.
99 \o \c waitingForOperand is \c true when the calculator is
100 expecting the user to start typing an operand.
101 \endlist
102
103 Additive and multiplicative operators are treated differently
104 because they have different precedences. For example, \gui{1 + 2 \unicode{247}
105 3} is interpreted as \gui{1 + (2 \unicode{247} 3)} because \gui{\unicode{247}} has higher
106 precedence than \gui{+}.
107
108 The table below shows the evolution of the calculator state as
109 the user enters a mathematical expression.
110
111 \table
112 \header \o User Input \o Display \o Sum so Far \o Add. Op. \o Factor so Far \o Mult. Op. \o Waiting for Operand?
113 \row \o \o 0 \o 0 \o \o \o \o \c true
114 \row \o \gui{1} \o 1 \o 0 \o \o \o \o \c false
115 \row \o \gui{1 +} \o 1 \o 1 \o \gui{+} \o \o \o \c true
116 \row \o \gui{1 + 2} \o 2 \o 1 \o \gui{+} \o \o \o \c false
117 \row \o \gui{1 + 2 \unicode{247}} \o 2 \o 1 \o \gui{+} \o 2 \o \gui{\unicode{247}} \o \c true
118 \row \o \gui{1 + 2 \unicode{247} 3} \o 3 \o 1 \o \gui{+} \o 2 \o \gui{\unicode{247}} \o \c false
119 \row \o \gui{1 + 2 \unicode{247} 3 -} \o 1.66667 \o 1.66667 \o \gui{-} \o \o \o \c true
120 \row \o \gui{1 + 2 \unicode{247} 3 - 4} \o 4 \o 1.66667 \o \gui{-} \o \o \o \c false
121 \row \o \gui{1 + 2 \unicode{247} 3 - 4 =} \o -2.33333 \o 0 \o \o \o \o \c true
122 \endtable
123
124 Unary operators, such as \gui Sqrt, require no special handling;
125 they can be applied immediately since the operand is already
126 known when the operator button is clicked.
127
128 \snippet examples/widgets/calculator/calculator.h 9
129 \codeline
130 \snippet examples/widgets/calculator/calculator.h 10
131
132 Finally, we declare the variables associated with the display and the
133 buttons used to display numerals.
134
135 \section1 Calculator Class Implementation
136
137 \snippet examples/widgets/calculator/calculator.cpp 0
138
139 In the constructor, we initialize the calculator's state. The \c
140 pendingAdditiveOperator and \c pendingMultiplicativeOperator
141 variables don't need to be initialized explicitly, because the
142 QString constructor initializes them to empty strings.
143
144 \snippet examples/widgets/calculator/calculator.cpp 1
145 \snippet examples/widgets/calculator/calculator.cpp 2
146
147 We create the QLineEdit representing the calculator's display and
148 set up some of its properties. In particular, we set it to be
149 read-only.
150
151 We also enlarge \c{display}'s font by 8 points.
152
153 \snippet examples/widgets/calculator/calculator.cpp 4
154
155 For each button, we call the private \c createButton() function with
156 the proper text label and a slot to connect to the button.
157
158 \snippet examples/widgets/calculator/calculator.cpp 5
159 \snippet examples/widgets/calculator/calculator.cpp 6
160
161 The layout is handled by a single QGridLayout. The
162 QLayout::setSizeConstraint() call ensures that the \c Calculator
163 widget is always shown as its optimal size (its
164 \l{QWidget::sizeHint()}{size hint}), preventing the user from
165 resizing the calculator. The size hint is determined by the size
166 and \l{QWidget::sizePolicy()}{size policy} of the child widgets.
167
168 Most child widgets occupy only one cell in the grid layout. For
169 these, we only need to pass a row and a column to
170 QGridLayout::addWidget(). The \c display, \c backspaceButton, \c
171 clearButton, and \c clearAllButton widgets occupy more than one
172 column; for these we must also pass a row span and a column
173 span.
174
175 \snippet examples/widgets/calculator/calculator.cpp 7
176
177 Pressing one of the calculator's digit buttons will emit the
178 button's \l{QToolButton::clicked()}{clicked()} signal, which will
179 trigger the \c digitClicked() slot.
180
181 First, we find out which button sent the signal using
182 QObject::sender(). This function returns the sender as a QObject
183 pointer. Since we know that the sender is a \c Button object, we
184 can safely cast the QObject. We could have used a C-style cast or
185 a C++ \c static_cast<>(), but as a defensive programming
186 technique we use a \l qobject_cast(). The advantage is that if
187 the object has the wrong type, a null pointer is returned.
188 Crashes due to null pointers are much easier to diagnose than
189 crashes due to unsafe casts. Once we have the button, we extract
190 the operator using QToolButton::text().
191
192 The slot needs to consider two situations in particular. If \c
193 display contains "0" and the user clicks the \gui{0} button, it
194 would be silly to show "00". And if the calculator is in
195 a state where it is waiting for a new operand,
196 the new digit is the first digit of that new operand; in that case,
197 any result of a previous calculation must be cleared first.
198
199 At the end, we append the new digit to the value in the display.
200
201 \snippet examples/widgets/calculator/calculator.cpp 8
202 \snippet examples/widgets/calculator/calculator.cpp 9
203
204 The \c unaryOperatorClicked() slot is called whenever one of the
205 unary operator buttons is clicked. Again a pointer to the clicked
206 button is retrieved using QObject::sender(). The operator is
207 extracted from the button's text and stored in \c
208 clickedOperator. The operand is obtained from \c display.
209
210 Then we perform the operation. If \gui Sqrt is applied to a
211 negative number or \gui{1/x} to zero, we call \c
212 abortOperation(). If everything goes well, we display the result
213 of the operation in the line edit and we set \c waitingForOperand
214 to \c true. This ensures that if the user types a new digit, the
215 digit will be considered as a new operand, instead of being
216 appended to the current value.
217
218 \snippet examples/widgets/calculator/calculator.cpp 10
219 \snippet examples/widgets/calculator/calculator.cpp 11
220
221 The \c additiveOperatorClicked() slot is called when the user
222 clicks the \gui{+} or \gui{-} button.
223
224 Before we can actually do something about the clicked operator,
225 we must handle any pending operations. We start with the
226 multiplicative operators, since these have higher precedence than
227 additive operators:
228
229 \snippet examples/widgets/calculator/calculator.cpp 12
230 \snippet examples/widgets/calculator/calculator.cpp 13
231
232 If \gui{\unicode{215}} or \gui{\unicode{247}} has been clicked earlier, without clicking
233 \gui{=} afterward, the current value in the display is the right
234 operand of the \gui{\unicode{215}} or \gui{\unicode{247}} operator and we can finally
235 perform the operation and update the display.
236
237 \snippet examples/widgets/calculator/calculator.cpp 14
238 \snippet examples/widgets/calculator/calculator.cpp 15
239
240 If \gui{+} or \gui{-} has been clicked earlier, \c sumSoFar is
241 the left operand and the current value in the display is the
242 right operand of the operator. If there is no pending additive
243 operator, \c sumSoFar is simply set to be the text in the
244 display.
245
246 \snippet examples/widgets/calculator/calculator.cpp 16
247 \snippet examples/widgets/calculator/calculator.cpp 17
248
249 Finally, we can take care of the operator that was just clicked.
250 Since we don't have the right-hand operand yet, we store the clicked
251 operator in the \c pendingAdditiveOperator variable. We will
252 apply the operation later, when we have a right operand, with \c
253 sumSoFar as the left operand.
254
255 \snippet examples/widgets/calculator/calculator.cpp 18
256
257 The \c multiplicativeOperatorClicked() slot is similar to \c
258 additiveOperatorClicked(). We don't need to worry about pending
259 additive operators here, because multiplicative operators have
260 precedence over additive operators.
261
262 \snippet examples/widgets/calculator/calculator.cpp 20
263
264 Like in \c additiveOperatorClicked(), we start by handing any
265 pending multiplicative and additive operators. Then we display \c
266 sumSoFar and reset the variable to zero. Resetting the variable
267 to zero is necessary to avoid counting the value twice.
268
269 \snippet examples/widgets/calculator/calculator.cpp 22
270
271 The \c pointClicked() slot adds a decimal point to the content in
272 \c display.
273
274 \snippet examples/widgets/calculator/calculator.cpp 24
275
276 The \c changeSignClicked() slot changes the sign of the value in
277 \c display. If the current value is positive, we prepend a minus
278 sign; if the current value is negative, we remove the first
279 character from the value (the minus sign).
280
281 \snippet examples/widgets/calculator/calculator.cpp 26
282
283 The \c backspaceClicked() removes the rightmost character in the
284 display. If we get an empty string, we show "0" and set \c
285 waitingForOperand to \c true.
286
287 \snippet examples/widgets/calculator/calculator.cpp 28
288
289 The \c clear() slot resets the current operand to zero. It is
290 equivalent to clicking \gui Backspace enough times to erase the
291 entire operand.
292
293 \snippet examples/widgets/calculator/calculator.cpp 30
294
295 The \c clearAll() slot resets the calculator to its initial state.
296
297 \snippet examples/widgets/calculator/calculator.cpp 32
298
299 The \c clearMemory() slot erases the sum kept in memory, \c
300 readMemory() displays the sum as an operand, \c setMemory()
301 replace the sum in memory with the current sum, and \c
302 addToMemory() adds the current value to the value in memory. For
303 \c setMemory() and \c addToMemory(), we start by calling \c
304 equalClicked() to update \c sumSoFar and the value in the
305 display.
306
307 \snippet examples/widgets/calculator/calculator.cpp 34
308
309 The private \c createButton() function is called from the
310 constructor to create calculator buttons.
311
312 \snippet examples/widgets/calculator/calculator.cpp 36
313
314 The private \c abortOperation() function is called whenever a
315 calculation fails. It resets the calculator state and displays
316 "####".
317
318 \snippet examples/widgets/calculator/calculator.cpp 38
319
320 The private \c calculate() function performs a binary operation.
321 The right operand is given by \c rightOperand. For additive
322 operators, the left operand is \c sumSoFar; for multiplicative
323 operators, the left operand is \c factorSoFar. The function
324 return \c false if a division by zero occurs.
325
326 \section1 Button Class Definition
327
328 Let's now take a look at the \c Button class:
329
330 \snippet examples/widgets/calculator/button.h 0
331
332 The \c Button class has a convenience constructor that takes a
333 text label and a parent widget, and it reimplements QWidget::sizeHint()
334 to provide more space around the text than the amount QToolButton
335 normally provides.
336
337 \section1 Button Class Implementation
338
339 \snippet examples/widgets/calculator/button.cpp 0
340
341 The buttons' appearance is determined by the layout of the
342 calculator widget through the size and
343 \l{QWidget::sizePolicy}{size policy} of the layout's child
344 widgets. The call to the
345 \l{QWidget::setSizePolicy()}{setSizePolicy()} function in the
346 constructor ensures that the button will expand horizontally to
347 fill all the available space; by default, \l{QToolButton}s don't
348 expand to fill available space. Without this call, the different
349 buttons in a same column would have different widths.
350
351 \snippet examples/widgets/calculator/button.cpp 1
352 \snippet examples/widgets/calculator/button.cpp 2
353
354 In \l{QWidget::sizeHint()}{sizeHint()}, we try to return a size
355 that looks good for most buttons. We reuse the size hint of the
356 base class (QToolButton) but modify it in the following ways:
357
358 \list
359 \o We add 20 to the \l{QSize::height()}{height} component of the size hint.
360 \o We make the \l{QSize::width()}{width} component of the size
361 hint at least as much as the \l{QSize::width()}{height}.
362 \endlist
363
364 This ensures that with most fonts, the digit and operator buttons
365 will be square, without truncating the text on the
366 \gui{Backspace}, \gui{Clear}, and \gui{Clear All} buttons.
367
368 The screenshot below shows how the \c Calculator widget would
369 look like if we \e didn't set the horizontal size policy to
370 QSizePolicy::Expanding in the constructor and if we didn't
371 reimplement QWidget::sizeHint().
372
373 \image calculator-ugly.png The Calculator example with default size policies and size hints
374
375*/
Note: See TracBrowser for help on using the repository browser.