doc/src/examples/transformations.qdoc
changeset 0 1918ee327afb
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 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:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 /*!
       
    43     \example painting/transformations
       
    44     \title Transformations Example
       
    45 
       
    46     The Transformations example shows how transformations influence
       
    47     the way that QPainter renders graphics primitives. In particular
       
    48     it shows how the order of transformations affect the result.
       
    49 
       
    50     \image transformations-example.png
       
    51 
       
    52     The application allows the user to manipulate the rendering of a
       
    53     shape by changing the translation, rotation and scale of
       
    54     QPainter's coordinate system.
       
    55 
       
    56     The example consists of two classes and a global enum:
       
    57 
       
    58     \list
       
    59     \o The \c RenderArea class controls the rendering of a given shape.
       
    60     \o The \c Window class is the application's main window.
       
    61     \o The \c Operation enum describes the various transformation
       
    62        operations available in the application.
       
    63     \endlist
       
    64 
       
    65     First we will take a quick look at the \c Operation enum, then we
       
    66     will review the \c RenderArea class to see how a shape is
       
    67     rendered. Finally, we will take a look at the Transformations
       
    68     application's features implemented in the \c Window class.
       
    69 
       
    70     \section1 Transformation Operations
       
    71 
       
    72     Normally, the QPainter operates on the associated device's own
       
    73     coordinate system, but it also has good support for coordinate
       
    74     transformations.
       
    75 
       
    76     The default coordinate system of a paint device has its origin at
       
    77     the top-left corner. The x values increase to the right and the y
       
    78     values increase downwards. You can scale the coordinate system by
       
    79     a given offset using the QPainter::scale() function, you can
       
    80     rotate it clockwise using the QPainter::rotate() function and you
       
    81     can translate it (i.e. adding a given offset to the points) using
       
    82     the QPainter::translate() function. You can also twist the
       
    83     coordinate system around the origin (called shearing) using the
       
    84     QPainter::shear() function.
       
    85 
       
    86     All the tranformation operations operate on QPainter's
       
    87     tranformation matrix that you can retrieve using the
       
    88     QPainter::worldTransform() function. A matrix transforms a point in the
       
    89     plane to another point. For more information about the
       
    90     transformation matrix, see the \l {The Coordinate System} and
       
    91     QTransform documentation.
       
    92 
       
    93     \snippet examples/painting/transformations/renderarea.h 0
       
    94 
       
    95     The global \c Operation enum is declared in the \c renderarea.h
       
    96     file and describes the various transformation operations available
       
    97     in the Transformations application.
       
    98 
       
    99     \section1 RenderArea Class Definition
       
   100 
       
   101     The \c RenderArea class inherits QWidget, and controls the
       
   102     rendering of a given shape.
       
   103 
       
   104     \snippet examples/painting/transformations/renderarea.h 1
       
   105 
       
   106     We declare two public functions, \c setOperations() and
       
   107     \c setShape(), to be able to specify the \c RenderArea widget's shape
       
   108     and to transform the coordinate system the shape is rendered
       
   109     within.
       
   110 
       
   111     We reimplement the QWidget's \l
       
   112     {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l
       
   113     {QWidget::sizeHint()}{sizeHint()} functions to give the \c
       
   114     RenderArea widget a reasonable size within our application, and we
       
   115     reimplement the QWidget::paintEvent() event handler to draw the
       
   116     render area's shape applying the user's transformation choices.
       
   117 
       
   118     \snippet examples/painting/transformations/renderarea.h 2
       
   119 
       
   120     We also declare several convenience functions to draw the shape,
       
   121     the coordinate system's outline and the coordinates, and to
       
   122     transform the painter according to the chosen transformations.
       
   123 
       
   124     In addition, the \c RenderArea widget keeps a list of the
       
   125     currently applied transformation operations, a reference to its
       
   126     shape, and a couple of convenience variables that we will use when
       
   127     rendering the coordinates.
       
   128 
       
   129     \section1 RenderArea Class Implementation
       
   130 
       
   131     The \c RenderArea widget controls the rendering of a given shape,
       
   132     including the transformations of the coordinate system, by
       
   133     reimplementing the QWidget::paintEvent() event handler. But first
       
   134     we will take a quick look at the constructor and at the functions
       
   135     that provides access to the \c RenderArea widget:
       
   136 
       
   137     \snippet examples/painting/transformations/renderarea.cpp 0
       
   138 
       
   139     In the constructor we pass the parent parameter on to the base
       
   140     class, and customize the font that we will use to render the
       
   141     coordinates. The QWidget::font() funtion returns the font
       
   142     currently set for the widget. As long as no special font has been
       
   143     set, or after QWidget::setFont() is called, this is either a
       
   144     special font for the widget class, the parent's font or (if this
       
   145     widget is a top level widget) the default application font.
       
   146 
       
   147     After ensuring that the font's size is 12 points, we extract the
       
   148     rectangles enclosing the coordinate letters, 'x' and 'y',  using the
       
   149     QFontMetrics class.
       
   150 
       
   151     QFontMetrics provides functions to access the individual metrics
       
   152     of the font, its characters, and for strings rendered in the
       
   153     font. The QFontMetrics::boundingRect() function returns the
       
   154     bounding rectangle of the given character relative to the
       
   155     left-most point on the base line.
       
   156 
       
   157     \snippet examples/painting/transformations/renderarea.cpp 1
       
   158     \codeline
       
   159     \snippet examples/painting/transformations/renderarea.cpp 2
       
   160 
       
   161     In the \c setShape() and \c setOperations() functions we update
       
   162     the \c RenderArea widget by storing the new value or values
       
   163     followed by a call to the QWidget::update() slot which schedules a
       
   164     paint event for processing when Qt returns to the main event loop.
       
   165 
       
   166     \snippet examples/painting/transformations/renderarea.cpp 3
       
   167     \codeline
       
   168     \snippet examples/painting/transformations/renderarea.cpp 4
       
   169 
       
   170     We reimplement the QWidget's \l
       
   171     {QWidget::minimumSizeHint()}{minimumSizeHint()} and \l
       
   172     {QWidget::sizeHint()}{sizeHint()} functions to give the \c
       
   173     RenderArea widget a reasonable size within our application. The
       
   174     default implementations of these functions returns an invalid size
       
   175     if there is no layout for this widget, and returns the layout's
       
   176     minimum size or preferred size, respectively, otherwise.
       
   177 
       
   178     \snippet examples/painting/transformations/renderarea.cpp 5
       
   179 
       
   180     The \c paintEvent() event handler recieves the \c RenderArea
       
   181     widget's paint events. A paint event is a request to repaint all
       
   182     or part of the widget. It can happen as a result of
       
   183     QWidget::repaint() or QWidget::update(), or because the widget was
       
   184     obscured and has now been uncovered, or for many other reasons.
       
   185 
       
   186     First we create a QPainter for the \c RenderArea widget. The \l
       
   187     {QPainter::RenderHint}{QPainter::Antialiasing} render hint
       
   188     indicates that the engine should antialias edges of primitives if
       
   189     possible. Then we erase the area that needs to be repainted using
       
   190     the QPainter::fillRect() function.
       
   191 
       
   192     We also translate the coordinate system with an constant offset to
       
   193     ensure that the original shape is renderend with a suitable
       
   194     margin.
       
   195 
       
   196     \snippet examples/painting/transformations/renderarea.cpp 6
       
   197 
       
   198     Before we start to render the shape, we call the QPainter::save()
       
   199     function.
       
   200 
       
   201     QPainter::save() saves the current painter state (i.e. pushes the
       
   202     state onto a stack) including the current coordinate system. The
       
   203     rationale for saving the painter state is that the following call
       
   204     to the \c transformPainter() function will transform the
       
   205     coordinate system depending on the currently chosen transformation
       
   206     operations, and we need a way to get back to the original state to
       
   207     draw the outline.
       
   208 
       
   209     After transforming the coordinate system, we draw the \c
       
   210     RenderArea's shape, and then we restore the painter state using
       
   211     the QPainter::restore() function (i.e. popping the saved state off
       
   212     the stack).
       
   213 
       
   214     \snippet examples/painting/transformations/renderarea.cpp 7
       
   215 
       
   216     Then we draw the square outline.
       
   217 
       
   218     \snippet examples/painting/transformations/renderarea.cpp 8
       
   219 
       
   220     Since we want the coordinates to correspond with the coordinate
       
   221     system the shape is rendered within, we must make another call to
       
   222     the \c transformPainter() function.
       
   223 
       
   224     The order of the painting operations is essential with respect to
       
   225     the shared pixels. The reason why we don't render the coordinates
       
   226     when the coordinate system already is transformed to render the
       
   227     shape, but instead defer their rendering to the end, is that we
       
   228     want the coordinates to appear on top of the shape and its
       
   229     outline.
       
   230 
       
   231     There is no need to save the QPainter state this time since
       
   232     drawing the coordinates is the last painting operation.
       
   233 
       
   234     \snippet examples/painting/transformations/renderarea.cpp 9
       
   235     \codeline
       
   236     \snippet examples/painting/transformations/renderarea.cpp 10
       
   237     \codeline
       
   238     \snippet examples/painting/transformations/renderarea.cpp 11
       
   239 
       
   240     The \c drawCoordinates(), \c drawOutline() and \c drawShape() are
       
   241     convenience functions called from the \c paintEvent() event
       
   242     handler. For more information about QPainter's basic drawing
       
   243     operations and how to display basic graphics primitives, see the
       
   244     \l {painting/basicdrawing}{Basic Drawing} example.
       
   245 
       
   246     \snippet examples/painting/transformations/renderarea.cpp 12
       
   247 
       
   248     The \c transformPainter() convenience function is also called from
       
   249     the \c paintEvent() event handler, and transforms the given
       
   250     QPainter's coordinate system according to the user's
       
   251     transformation choices.
       
   252 
       
   253     \section1 Window Class Definition
       
   254 
       
   255     The \c Window class is the Transformations application's main
       
   256     window.
       
   257 
       
   258     The application displays four \c RenderArea widgets. The left-most
       
   259     widget renders the shape in QPainter's default coordinate system,
       
   260     the others render the shape with the chosen transformation in
       
   261     addition to all the transformations applied to the \c RenderArea
       
   262     widgets to their left.
       
   263 
       
   264     \snippet examples/painting/transformations/window.h 0
       
   265 
       
   266     We declare two public slots to make the application able to
       
   267     respond to user interaction, updating the displayed \c RenderArea
       
   268     widgets according to the user's transformation choices.
       
   269 
       
   270     The \c operationChanged() slot updates each of the \c RenderArea
       
   271     widgets applying the currently chosen transformation operations, and
       
   272     is called whenever the user changes the selected operations. The
       
   273     \c shapeSelected() slot updates the \c RenderArea widgets' shapes
       
   274     whenever the user changes the preferred shape.
       
   275 
       
   276     \snippet examples/painting/transformations/window.h 1
       
   277 
       
   278     We also declare a private convenience function, \c setupShapes(),
       
   279     that is used when constructing the \c Window widget, and we
       
   280     declare pointers to the various components of the widget. We
       
   281     choose to keep the available shapes in a QList of \l
       
   282     {QPainterPath}s. In addition we declare a private enum counting
       
   283     the number of displayed \c RenderArea widgets except the widget
       
   284     that renders the shape in QPainter's default coordinate system.
       
   285 
       
   286     \section1 Window Class Implementation
       
   287 
       
   288     In the constructor we create and initialize the application's
       
   289     components:
       
   290 
       
   291     \snippet examples/painting/transformations/window.cpp 0
       
   292 
       
   293     First we create the \c RenderArea widget that will render the
       
   294     shape in the default coordinate system. We also create the
       
   295     associated QComboBox that allows the user to choose among four
       
   296     different shapes: A clock, a house, a text and a truck. The shapes
       
   297     themselves are created at the end of the constructor, using the
       
   298     \c setupShapes() convenience function.
       
   299 
       
   300     \snippet examples/painting/transformations/window.cpp 1
       
   301 
       
   302     Then we create the \c RenderArea widgets that will render their
       
   303     shapes with coordinate tranformations. By default the applied
       
   304     operation is \gui {No Transformation}, i.e. the shapes are
       
   305     rendered within the default coordinate system. We create and
       
   306     initialize the associated \l {QComboBox}es with items
       
   307     corresponding to the various transformation operations decribed by
       
   308     the global \c Operation enum.
       
   309 
       
   310     We also connect the \l {QComboBox}es' \l
       
   311     {QComboBox::activated()}{activated()} signal to the \c
       
   312     operationChanged() slot to update the application whenever the
       
   313     user changes the selected transformation operations.
       
   314 
       
   315     \snippet examples/painting/transformations/window.cpp 2
       
   316 
       
   317     Finally, we set the layout for the application window using the
       
   318     QWidget::setLayout() function, construct the available shapes
       
   319     using the private \c setupShapes() convenience function, and make
       
   320     the application show the clock shape on startup using the public
       
   321     \c shapeSelected() slot before we set the window title.
       
   322 
       
   323 
       
   324     \snippet examples/painting/transformations/window.cpp 3
       
   325     \snippet examples/painting/transformations/window.cpp 4
       
   326     \snippet examples/painting/transformations/window.cpp 5
       
   327     \snippet examples/painting/transformations/window.cpp 6
       
   328     \dots
       
   329 
       
   330     \snippet examples/painting/transformations/window.cpp 7
       
   331 
       
   332     The \c setupShapes() function is called from the constructor and
       
   333     create the QPainterPath objects representing the shapes that are
       
   334     used in the application. For construction details, see the \l
       
   335     {painting/transformations/window.cpp}{window.cpp} example
       
   336     file. The shapes are stored in a QList. The QList::append()
       
   337     function inserts the given shape at the end of the list.
       
   338 
       
   339     We also connect the associated QComboBox's \l
       
   340     {QComboBox::activated()}{activated()} signal to the \c
       
   341     shapeSelected() slot to update the application when the user
       
   342     changes the preferred shape.
       
   343 
       
   344     \snippet examples/painting/transformations/window.cpp 8
       
   345 
       
   346     The public \c operationChanged() slot is called whenever the user
       
   347     changes the selected operations.
       
   348 
       
   349     We retrieve the chosen transformation operation for each of the
       
   350     transformed \c RenderArea widgets by querying the associated \l
       
   351     {QComboBox}{QComboBoxes}. The transformed \c RenderArea widgets
       
   352     are supposed to render the shape with the transformation specified
       
   353     by its associated combobox \e {in addition to} all the
       
   354     transformations applied to the \c RenderArea widgets to its
       
   355     left. For that reason, for each widget we query, we append the
       
   356     associated operation to a QList of transformations which we apply
       
   357     to the widget before proceeding to the next.
       
   358 
       
   359     \snippet examples/painting/transformations/window.cpp 9
       
   360 
       
   361     The \c shapeSelected() slot is called whenever the user changes
       
   362     the preferred shape, updating the \c RenderArea widgets using
       
   363     their public \c setShape() function.
       
   364 
       
   365     \section1 Summary
       
   366 
       
   367     The Transformations example shows how transformations influence
       
   368     the way that QPainter renders graphics primitives. Normally, the
       
   369     QPainter operates on the device's own coordinate system, but it
       
   370     also has good support for coordinate transformations. With the
       
   371     Transformations application you can scale, rotate and translate
       
   372     QPainter's coordinate system.  The order in which these
       
   373     tranformations are applied is essential for the result.
       
   374 
       
   375     All the tranformation operations operate on QPainter's
       
   376     tranformation matrix. For more information about the
       
   377     transformation matrix, see the \l {The Coordinate System} and
       
   378     QTransform documentation.
       
   379 
       
   380     The Qt reference documentation provides several painting
       
   381     demos. Among these is the \l {demos/affine}{Affine
       
   382     Transformations} demo that shows Qt's ability to perform
       
   383     transformations on painting operations. The demo also allows the
       
   384     user to experiment with the various transformation operations.
       
   385 */