fc924ae47e
Widget examples were moved into a widgets subfolder, but qdoc references were not updated. Change-Id: Id2a4573e723745b9827c664c852807d6116f8f6d Reviewed-by: Casper van Donderen <casper.vandonderen@nokia.com>
376 lines
17 KiB
Plaintext
376 lines
17 KiB
Plaintext
/****************************************************************************
|
|
**
|
|
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
|
** Contact: http://www.qt-project.org/
|
|
**
|
|
** This file is part of the documentation of the Qt Toolkit.
|
|
**
|
|
** $QT_BEGIN_LICENSE:FDL$
|
|
** GNU Free Documentation License
|
|
** Alternatively, this file may be used under the terms of the GNU Free
|
|
** Documentation License version 1.3 as published by the Free Software
|
|
** Foundation and appearing in the file included in the packaging of
|
|
** this file.
|
|
**
|
|
** Other Usage
|
|
** Alternatively, this file may be used in accordance with the terms
|
|
** and conditions contained in a signed written agreement between you
|
|
** and Nokia.
|
|
**
|
|
**
|
|
**
|
|
**
|
|
**
|
|
** $QT_END_LICENSE$
|
|
**
|
|
****************************************************************************/
|
|
|
|
/*!
|
|
\example widgets/widgets/calculator
|
|
\title Calculator Example
|
|
|
|
The example shows how to use signals and slots to implement the
|
|
functionality of a calculator widget, and how to use QGridLayout
|
|
to place child widgets in a grid.
|
|
|
|
\image calculator-example.png Screenshot of the Calculator example
|
|
|
|
The example consists of two classes:
|
|
|
|
\list
|
|
\li \c Calculator is the calculator widget, with all the
|
|
calculator functionality.
|
|
\li \c Button is the widget used for each of the calculator
|
|
button. It derives from QToolButton.
|
|
\endlist
|
|
|
|
We will start by reviewing \c Calculator, then we will take a
|
|
look at \c Button.
|
|
|
|
\section1 Calculator Class Definition
|
|
|
|
\snippet widgets/widgets/calculator/calculator.h 0
|
|
|
|
The \c Calculator class provides a simple calculator widget. It
|
|
inherits from QDialog and has several private slots associated
|
|
with the calculator's buttons. QObject::eventFilter() is
|
|
reimplemented to handle mouse events on the calculator's display.
|
|
|
|
Buttons are grouped in categories according to their behavior.
|
|
For example, all the digit buttons (labeled \uicontrol 0 to \uicontrol 9)
|
|
append a digit to the current operand. For these, we connect
|
|
multiple buttons to the same slot (e.g., \c digitClicked()). The
|
|
categories are digits, unary operators (\uicontrol{Sqrt}, \uicontrol{x\unicode{178}},
|
|
\uicontrol{1/x}), additive operators (\uicontrol{+}, \uicontrol{-}), and
|
|
multiplicative operators (\uicontrol{\unicode{215}}, \uicontrol{\unicode{247}}). The other buttons
|
|
have their own slots.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.h 1
|
|
\snippet widgets/widgets/calculator/calculator.h 2
|
|
|
|
The private \c createButton() function is used as part of the
|
|
widget construction. \c abortOperation() is called whenever a
|
|
division by zero occurs or when a square root operation is
|
|
applied to a negative number. \c calculate() applies a binary
|
|
operator (\uicontrol{+}, \uicontrol{-}, \uicontrol{\unicode{215}}, or \uicontrol{\unicode{247}}).
|
|
|
|
\snippet widgets/widgets/calculator/calculator.h 3
|
|
\snippet widgets/widgets/calculator/calculator.h 4
|
|
\snippet widgets/widgets/calculator/calculator.h 5
|
|
\snippet widgets/widgets/calculator/calculator.h 6
|
|
\snippet widgets/widgets/calculator/calculator.h 7
|
|
\snippet widgets/widgets/calculator/calculator.h 8
|
|
|
|
These variables, together with the contents of the calculator
|
|
display (a QLineEdit), encode the state of the calculator:
|
|
|
|
\list
|
|
\li \c sumInMemory contains the value stored in the calculator's memory
|
|
(using \uicontrol{MS}, \uicontrol{M+}, or \uicontrol{MC}).
|
|
\li \c sumSoFar stores the value accumulated so far. When the user
|
|
clicks \uicontrol{=}, \c sumSoFar is recomputed and shown on the
|
|
display. \uicontrol{Clear All} resets \c sumSoFar to zero.
|
|
\li \c factorSoFar stores a temporary value when doing
|
|
multiplications and divisions.
|
|
\li \c pendingAdditiveOperator stores the last additive operator
|
|
clicked by the user.
|
|
\li \c pendingMultiplicativeOperator stores the last multiplicative operator
|
|
clicked by the user.
|
|
\li \c waitingForOperand is \c true when the calculator is
|
|
expecting the user to start typing an operand.
|
|
\endlist
|
|
|
|
Additive and multiplicative operators are treated differently
|
|
because they have different precedences. For example, \uicontrol{1 + 2 \unicode{247}
|
|
3} is interpreted as \uicontrol{1 + (2 \unicode{247} 3)} because \uicontrol{\unicode{247}} has higher
|
|
precedence than \uicontrol{+}.
|
|
|
|
The table below shows the evolution of the calculator state as
|
|
the user enters a mathematical expression.
|
|
|
|
\table
|
|
\header \li User Input \li Display \li Sum so Far \li Add. Op. \li Factor so Far \li Mult. Op. \li Waiting for Operand?
|
|
\row \li \li 0 \li 0 \li \li \li \li \c true
|
|
\row \li \uicontrol{1} \li 1 \li 0 \li \li \li \li \c false
|
|
\row \li \uicontrol{1 +} \li 1 \li 1 \li \uicontrol{+} \li \li \li \c true
|
|
\row \li \uicontrol{1 + 2} \li 2 \li 1 \li \uicontrol{+} \li \li \li \c false
|
|
\row \li \uicontrol{1 + 2 \unicode{247}} \li 2 \li 1 \li \uicontrol{+} \li 2 \li \uicontrol{\unicode{247}} \li \c true
|
|
\row \li \uicontrol{1 + 2 \unicode{247} 3} \li 3 \li 1 \li \uicontrol{+} \li 2 \li \uicontrol{\unicode{247}} \li \c false
|
|
\row \li \uicontrol{1 + 2 \unicode{247} 3 -} \li 1.66667 \li 1.66667 \li \uicontrol{-} \li \li \li \c true
|
|
\row \li \uicontrol{1 + 2 \unicode{247} 3 - 4} \li 4 \li 1.66667 \li \uicontrol{-} \li \li \li \c false
|
|
\row \li \uicontrol{1 + 2 \unicode{247} 3 - 4 =} \li -2.33333 \li 0 \li \li \li \li \c true
|
|
\endtable
|
|
|
|
Unary operators, such as \uicontrol Sqrt, require no special handling;
|
|
they can be applied immediately since the operand is already
|
|
known when the operator button is clicked.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.h 9
|
|
\codeline
|
|
\snippet widgets/widgets/calculator/calculator.h 10
|
|
|
|
Finally, we declare the variables associated with the display and the
|
|
buttons used to display numerals.
|
|
|
|
\section1 Calculator Class Implementation
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 0
|
|
|
|
In the constructor, we initialize the calculator's state. The \c
|
|
pendingAdditiveOperator and \c pendingMultiplicativeOperator
|
|
variables don't need to be initialized explicitly, because the
|
|
QString constructor initializes them to empty strings.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 1
|
|
\snippet widgets/widgets/calculator/calculator.cpp 2
|
|
|
|
We create the QLineEdit representing the calculator's display and
|
|
set up some of its properties. In particular, we set it to be
|
|
read-only.
|
|
|
|
We also enlarge \c{display}'s font by 8 points.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 4
|
|
|
|
For each button, we call the private \c createButton() function with
|
|
the proper text label and a slot to connect to the button.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 5
|
|
\snippet widgets/widgets/calculator/calculator.cpp 6
|
|
|
|
The layout is handled by a single QGridLayout. The
|
|
QLayout::setSizeConstraint() call ensures that the \c Calculator
|
|
widget is always shown as its optimal size (its
|
|
\l{QWidget::sizeHint()}{size hint}), preventing the user from
|
|
resizing the calculator. The size hint is determined by the size
|
|
and \l{QWidget::sizePolicy()}{size policy} of the child widgets.
|
|
|
|
Most child widgets occupy only one cell in the grid layout. For
|
|
these, we only need to pass a row and a column to
|
|
QGridLayout::addWidget(). The \c display, \c backspaceButton, \c
|
|
clearButton, and \c clearAllButton widgets occupy more than one
|
|
column; for these we must also pass a row span and a column
|
|
span.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 7
|
|
|
|
Pressing one of the calculator's digit buttons will emit the
|
|
button's \l{QToolButton::clicked()}{clicked()} signal, which will
|
|
trigger the \c digitClicked() slot.
|
|
|
|
First, we find out which button sent the signal using
|
|
QObject::sender(). This function returns the sender as a QObject
|
|
pointer. Since we know that the sender is a \c Button object, we
|
|
can safely cast the QObject. We could have used a C-style cast or
|
|
a C++ \c static_cast<>(), but as a defensive programming
|
|
technique we use a \l qobject_cast(). The advantage is that if
|
|
the object has the wrong type, a null pointer is returned.
|
|
Crashes due to null pointers are much easier to diagnose than
|
|
crashes due to unsafe casts. Once we have the button, we extract
|
|
the operator using QToolButton::text().
|
|
|
|
The slot needs to consider two situations in particular. If \c
|
|
display contains "0" and the user clicks the \uicontrol{0} button, it
|
|
would be silly to show "00". And if the calculator is in
|
|
a state where it is waiting for a new operand,
|
|
the new digit is the first digit of that new operand; in that case,
|
|
any result of a previous calculation must be cleared first.
|
|
|
|
At the end, we append the new digit to the value in the display.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 8
|
|
\snippet widgets/widgets/calculator/calculator.cpp 9
|
|
|
|
The \c unaryOperatorClicked() slot is called whenever one of the
|
|
unary operator buttons is clicked. Again a pointer to the clicked
|
|
button is retrieved using QObject::sender(). The operator is
|
|
extracted from the button's text and stored in \c
|
|
clickedOperator. The operand is obtained from \c display.
|
|
|
|
Then we perform the operation. If \uicontrol Sqrt is applied to a
|
|
negative number or \uicontrol{1/x} to zero, we call \c
|
|
abortOperation(). If everything goes well, we display the result
|
|
of the operation in the line edit and we set \c waitingForOperand
|
|
to \c true. This ensures that if the user types a new digit, the
|
|
digit will be considered as a new operand, instead of being
|
|
appended to the current value.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 10
|
|
\snippet widgets/widgets/calculator/calculator.cpp 11
|
|
|
|
The \c additiveOperatorClicked() slot is called when the user
|
|
clicks the \uicontrol{+} or \uicontrol{-} button.
|
|
|
|
Before we can actually do something about the clicked operator,
|
|
we must handle any pending operations. We start with the
|
|
multiplicative operators, since these have higher precedence than
|
|
additive operators:
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 12
|
|
\snippet widgets/widgets/calculator/calculator.cpp 13
|
|
|
|
If \uicontrol{\unicode{215}} or \uicontrol{\unicode{247}} has been clicked earlier, without clicking
|
|
\uicontrol{=} afterward, the current value in the display is the right
|
|
operand of the \uicontrol{\unicode{215}} or \uicontrol{\unicode{247}} operator and we can finally
|
|
perform the operation and update the display.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 14
|
|
\snippet widgets/widgets/calculator/calculator.cpp 15
|
|
|
|
If \uicontrol{+} or \uicontrol{-} has been clicked earlier, \c sumSoFar is
|
|
the left operand and the current value in the display is the
|
|
right operand of the operator. If there is no pending additive
|
|
operator, \c sumSoFar is simply set to be the text in the
|
|
display.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 16
|
|
\snippet widgets/widgets/calculator/calculator.cpp 17
|
|
|
|
Finally, we can take care of the operator that was just clicked.
|
|
Since we don't have the right-hand operand yet, we store the clicked
|
|
operator in the \c pendingAdditiveOperator variable. We will
|
|
apply the operation later, when we have a right operand, with \c
|
|
sumSoFar as the left operand.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 18
|
|
|
|
The \c multiplicativeOperatorClicked() slot is similar to \c
|
|
additiveOperatorClicked(). We don't need to worry about pending
|
|
additive operators here, because multiplicative operators have
|
|
precedence over additive operators.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 20
|
|
|
|
Like in \c additiveOperatorClicked(), we start by handing any
|
|
pending multiplicative and additive operators. Then we display \c
|
|
sumSoFar and reset the variable to zero. Resetting the variable
|
|
to zero is necessary to avoid counting the value twice.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 22
|
|
|
|
The \c pointClicked() slot adds a decimal point to the content in
|
|
\c display.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 24
|
|
|
|
The \c changeSignClicked() slot changes the sign of the value in
|
|
\c display. If the current value is positive, we prepend a minus
|
|
sign; if the current value is negative, we remove the first
|
|
character from the value (the minus sign).
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 26
|
|
|
|
The \c backspaceClicked() removes the rightmost character in the
|
|
display. If we get an empty string, we show "0" and set \c
|
|
waitingForOperand to \c true.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 28
|
|
|
|
The \c clear() slot resets the current operand to zero. It is
|
|
equivalent to clicking \uicontrol Backspace enough times to erase the
|
|
entire operand.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 30
|
|
|
|
The \c clearAll() slot resets the calculator to its initial state.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 32
|
|
|
|
The \c clearMemory() slot erases the sum kept in memory, \c
|
|
readMemory() displays the sum as an operand, \c setMemory()
|
|
replace the sum in memory with the current sum, and \c
|
|
addToMemory() adds the current value to the value in memory. For
|
|
\c setMemory() and \c addToMemory(), we start by calling \c
|
|
equalClicked() to update \c sumSoFar and the value in the
|
|
display.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 34
|
|
|
|
The private \c createButton() function is called from the
|
|
constructor to create calculator buttons.
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 36
|
|
|
|
The private \c abortOperation() function is called whenever a
|
|
calculation fails. It resets the calculator state and displays
|
|
"####".
|
|
|
|
\snippet widgets/widgets/calculator/calculator.cpp 38
|
|
|
|
The private \c calculate() function performs a binary operation.
|
|
The right operand is given by \c rightOperand. For additive
|
|
operators, the left operand is \c sumSoFar; for multiplicative
|
|
operators, the left operand is \c factorSoFar. The function
|
|
return \c false if a division by zero occurs.
|
|
|
|
\section1 Button Class Definition
|
|
|
|
Let's now take a look at the \c Button class:
|
|
|
|
\snippet widgets/widgets/calculator/button.h 0
|
|
|
|
The \c Button class has a convenience constructor that takes a
|
|
text label and a parent widget, and it reimplements QWidget::sizeHint()
|
|
to provide more space around the text than the amount QToolButton
|
|
normally provides.
|
|
|
|
\section1 Button Class Implementation
|
|
|
|
\snippet widgets/widgets/calculator/button.cpp 0
|
|
|
|
The buttons' appearance is determined by the layout of the
|
|
calculator widget through the size and
|
|
\l{QWidget::sizePolicy}{size policy} of the layout's child
|
|
widgets. The call to the
|
|
\l{QWidget::setSizePolicy()}{setSizePolicy()} function in the
|
|
constructor ensures that the button will expand horizontally to
|
|
fill all the available space; by default, \l{QToolButton}s don't
|
|
expand to fill available space. Without this call, the different
|
|
buttons in a same column would have different widths.
|
|
|
|
\snippet widgets/widgets/calculator/button.cpp 1
|
|
\snippet widgets/widgets/calculator/button.cpp 2
|
|
|
|
In \l{QWidget::sizeHint()}{sizeHint()}, we try to return a size
|
|
that looks good for most buttons. We reuse the size hint of the
|
|
base class (QToolButton) but modify it in the following ways:
|
|
|
|
\list
|
|
\li We add 20 to the \l{QSize::height()}{height} component of the size hint.
|
|
\li We make the \l{QSize::width()}{width} component of the size
|
|
hint at least as much as the \l{QSize::width()}{height}.
|
|
\endlist
|
|
|
|
This ensures that with most fonts, the digit and operator buttons
|
|
will be square, without truncating the text on the
|
|
\uicontrol{Backspace}, \uicontrol{Clear}, and \uicontrol{Clear All} buttons.
|
|
|
|
The screenshot below shows how the \c Calculator widget would
|
|
look like if we \e didn't set the horizontal size policy to
|
|
QSizePolicy::Expanding in the constructor and if we didn't
|
|
reimplement QWidget::sizeHint().
|
|
|
|
\image calculator-ugly.png The Calculator example with default size policies and size hints
|
|
|
|
*/
|