doc/src/examples/painterpaths.qdoc
changeset 7 f7bc934e204c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/src/examples/painterpaths.qdoc	Wed Mar 31 11:06:36 2010 +0300
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (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 Technology Preview License Agreement accompanying
+** this package.
+**
+** 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.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+    \example painting/painterpaths
+    \title Painter Paths Example
+
+    The Painter Paths example shows how painter paths can be used to
+    build complex shapes for rendering.
+
+    \image painterpaths-example.png
+
+    The QPainterPath class provides a container for painting
+    operations, enabling graphical shapes to be constructed and
+    reused.
+
+    A painter path is an object composed of a number of graphical
+    building blocks (such as rectangles, ellipses, lines, and curves),
+    and can be used for filling, outlining, and clipping. The main
+    advantage of painter paths over normal drawing operations is that
+    complex shapes only need to be created once, but they can be drawn
+    many times using only calls to QPainter::drawPath().
+
+    The example consists of two classes:
+
+    \list
+        \o The \c RenderArea class which is a custom widget displaying
+           a single painter path.
+        \o The \c Window class which is the applications main window
+           displaying several \c RenderArea widgets, and allowing the user
+           to manipulate the painter paths' filling, pen, color
+           and rotation angle.
+    \endlist
+
+    First we will review the \c Window class, then we will take a look
+    at the \c RenderArea class.
+
+    \section1 Window Class Definition
+
+    The \c Window class inherits QWidget, and is the applications main
+    window displaying several \c RenderArea widgets, and allowing the
+    user to manipulate the painter paths' filling, pen, color and
+    rotation angle.
+
+    \snippet examples/painting/painterpaths/window.h 0
+
+    We declare three private slots to respond to user input regarding
+    filling and color: \c fillRuleChanged(), \c fillGradientChanged()
+    and \c penColorChanged().
+
+    When the user changes the pen width and the rotation angle, the
+    new value is passed directly on to the \c RenderArea widgets using
+    the QSpinBox::valueChanged() signal. The reason why we must
+    implement slots to update the filling and color, is that QComboBox
+    doesn't provide a similar signal passing the new value as
+    argument; so we need to retrieve the new value, or values, before
+    we can update the \c RenderArea widgets.
+
+    \snippet examples/painting/painterpaths/window.h 1
+
+    We also declare a couple of private convenience functions: \c
+    populateWithColors() populates a given QComboBox with items
+    corresponding to the color names Qt knows about, and \c
+    currentItemData() returns the current item for a given QComboBox.
+
+    \snippet examples/painting/painterpaths/window.h 2
+
+    Then we declare the various components of the main window
+    widget. We also declare a convenience constant specifying the
+    number of \c RenderArea widgets.
+
+    \section1 Window Class Implementation
+
+    In the implementation of the \c Window class we first declare the
+    constant \c Pi with six significant figures:
+
+    \snippet examples/painting/painterpaths/window.cpp 0
+
+    In the constructor, we then define the various painter paths and
+    create corresponding \c RenderArea widgets which will render the
+    graphical shapes:
+
+    \snippet examples/painting/painterpaths/window.cpp 1
+
+    We construct a rectangle with sharp corners using the
+    QPainterPath::moveTo() and QPainterPath::lineTo()
+    functions.
+
+    QPainterPath::moveTo() moves the current point to the point passed
+    as argument. A painter path is an object composed of a number of
+    graphical building blocks, i.e. subpaths. Moving the current point
+    will also start a new subpath (implicitly closing the previously
+    current path when the new one is started). The
+    QPainterPath::lineTo() function adds a straight line from the
+    current point to the given end point. After the line is drawn, the
+    current point is updated to be at the end point of the line.
+
+    We first move the current point starting a new subpath, and we
+    draw three of the rectangle's sides. Then we call the
+    QPainterPath::closeSubpath() function which draws a line to the
+    beginning of the current subpath. A new subpath is automatically
+    begun when the current subpath is closed. The current point of the
+    new path is (0, 0). We could also have called
+    QPainterPath::lineTo() to draw the last line as well, and then
+    explicitly start a new subpath using the QPainterPath::moveTo()
+    function.
+
+    QPainterPath also provide the QPainterPath::addRect() convenience
+    function, which adds a given rectangle to the path as a closed
+    subpath. The rectangle is added as a clockwise set of lines. The
+    painter path's current position after the rect has been added is
+    at the top-left corner of the rectangle.
+
+    \snippet examples/painting/painterpaths/window.cpp 2
+
+    Then we construct a rectangle with rounded corners. As before, we
+    use the QPainterPath::moveTo() and QPainterPath::lineTo()
+    functions to draw the rectangle's sides. To create the rounded
+    corners we use the QPainterPath::arcTo() function.
+
+    QPainterPath::arcTo() creates an arc that occupies the given
+    rectangle (specified by a QRect or the rectangle's coordinates),
+    beginning at the given start angle and extending the given degrees
+    counter-clockwise. Angles are specified in degrees. Clockwise arcs
+    can be specified using negative angles.  The function connects the
+    current point to the starting point of the arc if they are not
+    already connected.
+
+    \snippet examples/painting/painterpaths/window.cpp 3
+
+    We also use the QPainterPath::arcTo() function to construct the
+    ellipse path. First we move the current point starting a new
+    path. Then we call QPainterPath::arcTo() with starting angle 0.0
+    and 360.0 degrees as the last argument, creating an ellipse.
+
+    Again, QPainterPath provides a convenience function (
+    QPainterPath::addEllipse()) which creates an ellipse within a
+    given bounding rectangle and adds it to the painter path. If the
+    current subpath is closed, a new subpath is started. The ellipse
+    is composed of a clockwise curve, starting and finishing at zero
+    degrees (the 3 o'clock position).
+
+    \snippet examples/painting/painterpaths/window.cpp 4
+
+    When constructing the pie chart path we continue to use a
+    combination of the mentioned functions: First we move the current
+    point, starting a new subpath. Then we create a line from the
+    center of the chart to the arc, and the arc itself. When we close
+    the subpath, we implicitly construct the last line back to the
+    center of the chart.
+
+    \snippet examples/painting/painterpaths/window.cpp 5
+
+    Constructing a polygon is equivalent to constructing a rectangle.
+
+    QPainterPath also provide the QPainterPath::addPolygon()
+    convenience function which adds the given polygon to the path as a
+    new subpath. Current position after the polygon has been added is
+    the last point in polygon.
+
+    \snippet examples/painting/painterpaths/window.cpp 6
+
+    Then we create a path consisting of a group of subpaths: First we
+    move the current point, and create a circle using the
+    QPainterPath::arcTo() function with starting angle 0.0, and 360
+    degrees as the last argument, as we did when we created the
+    ellipse path. Then we move the current point again, starting a
+    new subpath, and construct three sides of a square using the
+    QPainterPath::lineTo() function.
+
+    Now, when we call the QPainterPath::closeSubpath() fucntion the
+    last side is created. Remember that the
+    QPainterPath::closeSubpath() function draws a line to the
+    beginning of the \e current subpath, i.e the square.
+
+    QPainterPath provide a convenience function,
+    QPainterPath::addPath() which adds a given path to the path that
+    calls the function.
+
+    \snippet examples/painting/painterpaths/window.cpp 7
+
+    When creating the text path, we first create the font. Then we set
+    the font's style strategy which tells the font matching algorithm
+    what type of fonts should be used to find an appropriate default
+    family. QFont::ForceOutline forces the use of outline fonts.
+
+    To construct the text, we use the QPainterPath::addText() function
+    which adds the given text to the path as a set of closed subpaths
+    created from the supplied font. The subpaths are positioned so
+    that the left end of the text's baseline lies at the specified
+    point.
+
+    \snippet examples/painting/painterpaths/window.cpp 8
+
+    To create the Bezier path, we use the QPainterPath::cubicTo()
+    function which adds a Bezier curve between the current point and
+    the given end point with the given control point.  After the curve
+    is added, the current point is updated to be at the end point of
+    the curve.
+
+    In this case we omit to close the subpath so that we only have a
+    simple curve. But there is still a logical line from the curve's
+    endpoint back to the beginning of the subpath; it becomes visible
+    when filling the path as can be seen in the applications main
+    window.
+
+    \snippet examples/painting/painterpaths/window.cpp 9
+
+    The final path that we construct shows that you can use
+    QPainterPath to construct rather complex shapes using only the
+    previous mentioned QPainterPath::moveTo(), QPainterPath::lineTo()
+    and QPainterPath::closeSubpath() functions.
+
+    \snippet examples/painting/painterpaths/window.cpp 10
+
+    Now that we have created all the painter paths that we need, we
+    create a corresponding \c RenderArea widget for each. In the end,
+    we make sure that the number of render areas is correct using the
+    Q_ASSERT() macro.
+
+    \snippet examples/painting/painterpaths/window.cpp 11
+
+    Then we create the widgets associated with the painter paths' fill
+    rule.
+
+    There are two available fill rules in Qt: The Qt::OddEvenFill rule
+    determine whether a point is inside the shape by drawing a
+    horizontal line from the point to a location outside the shape,
+    and count the number of intersections. If the number of
+    intersections is an odd number, the point is inside the
+    shape. This rule is the default.
+
+    The Qt::WindingFill rule determine whether a point is inside the
+    shape by drawing a horizontal line from the point to a location
+    outside the shape. Then it determines whether the direction of the
+    line at each intersection point is up or down. The winding number
+    is determined by summing the direction of each intersection. If
+    the number is non zero, the point is inside the shape.
+
+    The Qt::WindingFill rule can in most cases be considered as the
+    intersection of closed shapes.
+
+    \snippet examples/painting/painterpaths/window.cpp 12
+
+    We also create the other widgets associated with the filling, the
+    pen and the rotation angle.
+
+    \snippet examples/painting/painterpaths/window.cpp 16
+
+    We connect the comboboxes \l {QComboBox::activated()}{activated()}
+    signals to the associated slots in the \c Window class, while we
+    connect the spin boxes \l
+    {QSpinBox::valueChanged()}{valueChanged()} signal directly to the
+    \c RenderArea widget's respective slots.
+
+    \snippet examples/painting/painterpaths/window.cpp 17
+
+    We add the \c RenderArea widgets to a separate layout which we
+    then add to the main layout along with the rest of the widgets.
+
+    \snippet examples/painting/painterpaths/window.cpp 18
+
+    Finally, we initialize the \c RenderArea widgets by calling the \c
+    fillRuleChanged(), \c fillGradientChanged() and \c
+    penColorChanged() slots, and we set the inital pen width and
+    window title.
+
+    \snippet examples/painting/painterpaths/window.cpp 19
+    \codeline
+    \snippet examples/painting/painterpaths/window.cpp 20
+    \codeline
+    \snippet examples/painting/painterpaths/window.cpp 21
+
+    The private slots are implemented to retrieve the new value, or
+    values, from the associated comboboxes and update the RenderArea
+    widgets.
+
+    First we determine the new value, or values, using the private \c
+    currentItemData() function and the qvariant_cast() template
+    function. Then we call the associated slot for each of the \c
+    RenderArea widgets to update the painter paths.
+
+    \snippet examples/painting/painterpaths/window.cpp 22
+
+    The \c populateWithColors() function populates the given combobox
+    with items corresponding to the color names Qt knows about
+    provided by the static QColor::colorNames() function.
+
+    \snippet examples/painting/painterpaths/window.cpp 23
+
+    The \c currentItemData() function simply return the current item
+    of the given combobox.
+
+    \section1 RenderArea Class Definition
+
+    The \c RenderArea class inherits QWidget, and is a custom widget
+    displaying a single painter path.
+
+    \snippet examples/painting/painterpaths/renderarea.h 0
+
+    We declare several public slots updating the \c RenderArea
+    widget's associated painter path. In addition we reimplement the
+    QWidget::minimumSizeHint() and QWidget::sizeHint() functions to
+    give the \c RenderArea widget a reasonable size within our
+    application, and we reimplement the QWidget::paintEvent() event
+    handler to draw its painter path.
+
+    \snippet examples/painting/painterpaths/renderarea.h 1
+
+    Each instance of the \c RenderArea class has a QPainterPath, a
+    couple of fill colors, a pen width, a pen color and a rotation
+    angle.
+
+    \section1 RenderArea Class Implementation
+
+    The constructor takes a QPainterPath as argument (in addition to
+    the optional QWidget parent):
+
+    \snippet examples/painting/painterpaths/renderarea.cpp 0
+
+    In the constructor we initialize the \c RenderArea widget with the
+    QPainterPath parameter as well as initializing the pen width and
+    rotation angle. We also set the widgets \l
+    {QWidget::backgroundRole()}{background role}; QPalette::Base is
+    typically white.
+
+    \snippet examples/painting/painterpaths/renderarea.cpp 1
+    \codeline
+    \snippet examples/painting/painterpaths/renderarea.cpp 2
+
+    Then we reimplement the QWidget::minimumSizeHint() and
+    QWidget::sizeHint() functions to give the \c RenderArea widget a
+    reasonable size within our application.
+
+    \snippet examples/painting/painterpaths/renderarea.cpp 3
+    \codeline
+    \snippet examples/painting/painterpaths/renderarea.cpp 4
+    \codeline
+    \snippet examples/painting/painterpaths/renderarea.cpp 5
+    \codeline
+    \snippet examples/painting/painterpaths/renderarea.cpp 6
+    \codeline
+    \snippet examples/painting/painterpaths/renderarea.cpp 7
+
+    The various public slots updates the \c RenderArea widget's
+    painter path by setting the associated property and make a call to
+    the QWidget::update() function, forcing a repaint of the widget
+    with the new rendering preferences.
+
+    The QWidget::update() slot does not cause an immediate repaint;
+    instead it schedules a paint event for processing when Qt returns
+    to the main event loop.
+
+    \snippet examples/painting/painterpaths/renderarea.cpp 8
+
+    A paint event is a request to repaint all or parts of the
+    widget. The paintEvent() function is an event handler that can be
+    reimplemented to receive the widget's paint events. We reimplement
+    the event handler to render the \c RenderArea widget's painter
+    path.
+
+    First, we create a QPainter for the \c RenderArea instance, and
+    set the painter's render hints. The QPainter::RenderHints are used
+    to specify flags to QPainter that may, or may not, be respected by
+    any given engine. QPainter::Antialiasing indicates that the engine
+    should anti-alias the edges of primitives if possible, i.e. put
+    additional pixels around the original ones to smooth the edges.
+
+    \snippet examples/painting/painterpaths/renderarea.cpp 9
+
+    Then we scale the QPainter's coordinate system to ensure that the
+    painter path is rendered in the right size, i.e that it grows with
+    the \c RenderArea widget when the application is resized. When we
+    constructed the various painter paths, they were all rnedered
+    within a square with a 100 pixel width wich is equivalent to \c
+    RenderArea::sizeHint(). The QPainter::scale() function scales the
+    coordinate system by the \c RenderArea widget's \e current width
+    and height divided by 100.
+
+    Now, when we are sure that the painter path has the right size, we
+    can translate the coordinate system to make the painter path
+    rotate around the \c RenderArea widget's center. After we have
+    performed the rotation, we must remember to translate the
+    coordinate system back again.
+
+    \snippet examples/painting/painterpaths/renderarea.cpp 10
+
+    Then we set the QPainter's pen with the instance's rendering
+    preferences. We create a QLinearGradient and set its colors
+    corresponding to the \c RenderArea widget's fill colors. Finally,
+    we set the QPainter's brush (the gradient is automatically
+    converted into a QBrush), and draw the \c RenderArea widget's
+    painter path using the QPainter::drawPath() function.
+*/