diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /doc/src/examples/transformations.qdoc | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'doc/src/examples/transformations.qdoc')
-rw-r--r-- | doc/src/examples/transformations.qdoc | 385 |
1 files changed, 385 insertions, 0 deletions
diff --git a/doc/src/examples/transformations.qdoc b/doc/src/examples/transformations.qdoc new file mode 100644 index 0000000..eabb803 --- /dev/null +++ b/doc/src/examples/transformations.qdoc @@ -0,0 +1,385 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example painting/transformations + \title Transformations Example + + The Transformations example shows how transformations influence + the way that QPainter renders graphics primitives. In particular + it shows how the order of transformations affect the result. + + \image transformations-example.png + + The application allows the user to manipulate the rendering of a + shape by changing the translation, rotation and scale of + QPainter's coordinate system. + + The example consists of two classes and a global enum: + + \list + \o The \c RenderArea class controls the rendering of a given shape. + \o The \c Window class is the application's main window. + \o The \c Operation enum describes the various transformation + operations available in the application. + \endlist + + First we will take a quick look at the \c Operation enum, then we + will review the \c RenderArea class to see how a shape is + rendered. Finally, we will take a look at the Transformations + application's features implemented in the \c Window class. + + \section1 Transformation Operations + + Normally, the QPainter operates on the associated device's own + coordinate system, but it also has good support for coordinate + transformations. + + The default coordinate system of a paint device has its origin at + the top-left corner. The x values increase to the right and the y + values increase downwards. You can scale the coordinate system by + a given offset using the QPainter::scale() function, you can + rotate it clockwise using the QPainter::rotate() function and you + can translate it (i.e. adding a given offset to the points) using + the QPainter::translate() function. You can also twist the + coordinate system around the origin (called shearing) using the + QPainter::shear() function. + + All the tranformation operations operate on QPainter's + tranformation matrix that you can retrieve using the + QPainter::matrix() function. A matrix transforms a point in the + plane to another point. For more information about the + transformation matrix, see the \l {The Coordinate System} and + QMatrix documentation. + + \snippet examples/painting/transformations/renderarea.h 0 + + The global \c Operation enum is declared in the \c renderarea.h + file and describes the various transformation operations available + in the Transformations application. + + \section1 RenderArea Class Definition + + The \c RenderArea class inherits QWidget, and controls the + rendering of a given shape. + + \snippet examples/painting/transformations/renderarea.h 1 + + We declare two public functions, \c setOperations() and + \c setShape(), to be able to specify the \c RenderArea widget's shape + and to transform the coordinate system the shape is rendered + within. + + We reimplement the QWidget's \l + {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l + {QWidget::sizeHint()}{sizeHint()} functions to give the \c + RenderArea widget a reasonable size within our application, and we + reimplement the QWidget::paintEvent() event handler to draw the + render area's shape applying the user's transformation choices. + + \snippet examples/painting/transformations/renderarea.h 2 + + We also declare several convenience functions to draw the shape, + the coordinate system's outline and the coordinates, and to + transform the painter according to the chosen transformations. + + In addition, the \c RenderArea widget keeps a list of the + currently applied transformation operations, a reference to its + shape, and a couple of convenience variables that we will use when + rendering the coordinates. + + \section1 RenderArea Class Implementation + + The \c RenderArea widget controls the rendering of a given shape, + including the transformations of the coordinate system, by + reimplementing the QWidget::paintEvent() event handler. But first + we will take a quick look at the constructor and at the functions + that provides access to the \c RenderArea widget: + + \snippet examples/painting/transformations/renderarea.cpp 0 + + In the constructor we pass the parent parameter on to the base + class, and customize the font that we will use to render the + coordinates. The QWidget::font() funtion returns the font + currently set for the widget. As long as no special font has been + set, or after QWidget::setFont() is called, this is either a + special font for the widget class, the parent's font or (if this + widget is a top level widget) the default application font. + + After ensuring that the font's size is 12 points, we extract the + rectangles enclosing the coordinate letters, 'x' and 'y', using the + QFontMetrics class. + + QFontMetrics provides functions to access the individual metrics + of the font, its characters, and for strings rendered in the + font. The QFontMetrics::boundingRect() function returns the + bounding rectangle of the given character relative to the + left-most point on the base line. + + \snippet examples/painting/transformations/renderarea.cpp 1 + \codeline + \snippet examples/painting/transformations/renderarea.cpp 2 + + In the \c setShape() and \c setOperations() functions we update + the \c RenderArea widget by storing the new value or values + followed by a call to the QWidget::update() slot which schedules a + paint event for processing when Qt returns to the main event loop. + + \snippet examples/painting/transformations/renderarea.cpp 3 + \codeline + \snippet examples/painting/transformations/renderarea.cpp 4 + + We reimplement the QWidget's \l + {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l + {QWidget::sizeHint()}{sizeHint()} functions to give the \c + RenderArea widget a reasonable size within our application. The + default implementations of these functions returns an invalid size + if there is no layout for this widget, and returns the layout's + minimum size or preferred size, respectively, otherwise. + + \snippet examples/painting/transformations/renderarea.cpp 5 + + The \c paintEvent() event handler recieves the \c RenderArea + widget's paint events. A paint event is a request to repaint all + or part of the widget. It can happen as a result of + QWidget::repaint() or QWidget::update(), or because the widget was + obscured and has now been uncovered, or for many other reasons. + + First we create a QPainter for the \c RenderArea widget. The \l + {QPainter::RenderHint}{QPainter::Antialiasing} render hint + indicates that the engine should antialias edges of primitives if + possible. Then we erase the area that needs to be repainted using + the QPainter::fillRect() function. + + We also translate the coordinate system with an constant offset to + ensure that the original shape is renderend with a suitable + margin. + + \snippet examples/painting/transformations/renderarea.cpp 6 + + Before we start to render the shape, we call the QPainter::save() + function. + + QPainter::save() saves the current painter state (i.e. pushes the + state onto a stack) including the current coordinate system. The + rationale for saving the painter state is that the following call + to the \c transformPainter() function will transform the + coordinate system depending on the currently chosen transformation + operations, and we need a way to get back to the original state to + draw the outline. + + After transforming the coordinate system, we draw the \c + RenderArea's shape, and then we restore the painter state using + the the QPainter::restore() function (i.e. popping the saved state off + the stack). + + \snippet examples/painting/transformations/renderarea.cpp 7 + + Then we draw the square outline. + + \snippet examples/painting/transformations/renderarea.cpp 8 + + Since we want the coordinates to correspond with the coordinate + system the shape is rendered within, we must make another call to + the \c transformPainter() function. + + The order of the painting operations is essential with respect to + the shared pixels. The reason why we don't render the coordinates + when the coordinate system already is transformed to render the + shape, but instead defer their rendering to the end, is that we + want the coordinates to appear on top of the shape and its + outline. + + There is no need to save the QPainter state this time since + drawing the coordinates is the last painting operation. + + \snippet examples/painting/transformations/renderarea.cpp 9 + \codeline + \snippet examples/painting/transformations/renderarea.cpp 10 + \codeline + \snippet examples/painting/transformations/renderarea.cpp 11 + + The \c drawCoordinates(), \c drawOutline() and \c drawShape() are + convenience functions called from the \c paintEvent() event + handler. For more information about QPainter's basic drawing + operations and how to display basic graphics primitives, see the + \l {painting/basicdrawing}{Basic Drawing} example. + + \snippet examples/painting/transformations/renderarea.cpp 12 + + The \c transformPainter() convenience function is also called from + the \c paintEvent() event handler, and transforms the given + QPainter's coordinate system according to the user's + transformation choices. + + \section1 Window Class Definition + + The \c Window class is the Transformations application's main + window. + + The application displays four \c RenderArea widgets. The left-most + widget renders the shape in QPainter's default coordinate system, + the others render the shape with the chosen transformation in + addition to all the transformations applied to the \c RenderArea + widgets to their left. + + \snippet examples/painting/transformations/window.h 0 + + We declare two public slots to make the application able to + respond to user interaction, updating the displayed \c RenderArea + widgets according to the user's transformation choices. + + The \c operationChanged() slot updates each of the \c RenderArea + widgets applying the currently chosen transformation operations, and + is called whenever the user changes the selected operations. The + \c shapeSelected() slot updates the \c RenderArea widgets' shapes + whenever the user changes the preferred shape. + + \snippet examples/painting/transformations/window.h 1 + + We also declare a private convenience function, \c setupShapes(), + that is used when constructing the \c Window widget, and we + declare pointers to the various components of the widget. We + choose to keep the available shapes in a QList of \l + {QPainterPath}s. In addition we declare a private enum counting + the number of displayed \c RenderArea widgets except the widget + that renders the shape in QPainter's default coordinate system. + + \section1 Window Class Implementation + + In the constructor we create and initialize the application's + components: + + \snippet examples/painting/transformations/window.cpp 0 + + First we create the \c RenderArea widget that will render the + shape in the default coordinate system. We also create the + associated QComboBox that allows the user to choose among four + different shapes: A clock, a house, a text and a truck. The shapes + themselves are created at the end of the constructor, using the + \c setupShapes() convenience function. + + \snippet examples/painting/transformations/window.cpp 1 + + Then we create the \c RenderArea widgets that will render their + shapes with coordinate tranformations. By default the applied + operation is \gui {No Transformation}, i.e. the shapes are + rendered within the default coordinate system. We create and + initialize the associated \l {QComboBox}es with items + corresponding to the various transformation operations decribed by + the global \c Operation enum. + + We also connect the \l {QComboBox}es' \l + {QComboBox::activated()}{activated()} signal to the \c + operationChanged() slot to update the application whenever the + user changes the selected transformation operations. + + \snippet examples/painting/transformations/window.cpp 2 + + Finally, we set the layout for the application window using the + QWidget::setLayout() function, construct the available shapes + using the private \c setupShapes() convenience function, and make + the application show the clock shape on startup using the public + \c shapeSelected() slot before we set the window title. + + + \snippet examples/painting/transformations/window.cpp 3 + \snippet examples/painting/transformations/window.cpp 4 + \snippet examples/painting/transformations/window.cpp 5 + \snippet examples/painting/transformations/window.cpp 6 + \dots + + \snippet examples/painting/transformations/window.cpp 7 + + The \c setupShapes() function is called from the constructor and + create the QPainterPath objects representing the shapes that are + used in the application. For construction details, see the \l + {painting/transformations/window.cpp}{window.cpp} example + file. The shapes are stored in a QList. The QList::append() + function inserts the given shape at the end of the list. + + We also connect the associated QComboBox's \l + {QComboBox::activated()}{activated()} signal to the \c + shapeSelected() slot to update the application when the user + changes the preferred shape. + + \snippet examples/painting/transformations/window.cpp 8 + + The public \c operationChanged() slot is called whenever the user + changes the selected operations. + + We retrieve the chosen transformation operation for each of the + transformed \c RenderArea widgets by querying the associated \l + {QComboBox}{QComboBoxes}. The transformed \c RenderArea widgets + are supposed to render the shape with the transformation specified + by its associated combobox \e {in addition to} all the + transformations applied to the \c RenderArea widgets to its + left. For that reason, for each widget we query, we append the + associated operation to a QList of transformations which we apply + to the widget before proceeding to the next. + + \snippet examples/painting/transformations/window.cpp 9 + + The \c shapeSelected() slot is called whenever the user changes + the preferred shape, updating the \c RenderArea widgets using + their public \c setShape() function. + + \section1 Summary + + The Transformations example shows how transformations influence + the way that QPainter renders graphics primitives. Normally, the + QPainter operates on the device's own coordinate system, but it + also has good support for coordinate transformations. With the + Transformations application you can scale, rotate and translate + QPainter's coordinate system. The order in which these + tranformations are applied is essential for the result. + + All the tranformation operations operate on QPainter's + tranformation matrix. For more information about the + transformation matrix, see the \l {The Coordinate System} and + QMatrix documentation. + + The Qt reference documentation provides several painting + demos. Among these is the \l {demos/affine}{Affine + Transformations} demo that shows Qt's ability to perform + transformations on painting operations. The demo also allows the + user to experiment with the various transformation operations. +*/ |