summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2010-05-12 14:32:12 (GMT)
committerAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2010-05-12 14:36:10 (GMT)
commit812f78e55aa3db4d51ec8617320358d80c4a71d5 (patch)
treeaaceddad76df5b4d91bd2de4d56bb21b73ca94fa
parente4902b4f25ca9c1ecff99609dbe376b407d9c6c5 (diff)
downloadQt-812f78e55aa3db4d51ec8617320358d80c4a71d5.zip
Qt-812f78e55aa3db4d51ec8617320358d80c4a71d5.tar.gz
Qt-812f78e55aa3db4d51ec8617320358d80c4a71d5.tar.bz2
Documentation for the Pad Navigator Example.
This also does a few touch-ups on the source code.
-rw-r--r--doc/src/examples/padnavigator.qdoc552
-rw-r--r--doc/src/getting-started/examples.qdoc1
-rw-r--r--examples/graphicsview/padnavigator/flippablepad.cpp27
-rw-r--r--examples/graphicsview/padnavigator/flippablepad.h5
-rw-r--r--examples/graphicsview/padnavigator/main.cpp2
-rw-r--r--examples/graphicsview/padnavigator/padnavigator.cpp218
-rw-r--r--examples/graphicsview/padnavigator/padnavigator.h6
-rw-r--r--examples/graphicsview/padnavigator/roundrectitem.cpp19
-rw-r--r--examples/graphicsview/padnavigator/roundrectitem.h5
-rw-r--r--examples/graphicsview/padnavigator/splashitem.cpp10
-rw-r--r--examples/graphicsview/padnavigator/splashitem.h2
11 files changed, 736 insertions, 111 deletions
diff --git a/doc/src/examples/padnavigator.qdoc b/doc/src/examples/padnavigator.qdoc
index 70e131e..e29a3b2 100644
--- a/doc/src/examples/padnavigator.qdoc
+++ b/doc/src/examples/padnavigator.qdoc
@@ -43,9 +43,555 @@
\example graphicsview/padnavigator
\title Pad Navigator Example
- The Pad Navigator Example shows how you can use Graphics View
- together with embedded widgets to create a simple but useful
- dynamic user interface for embedded devices.
+ The Pad Navigator Example shows how you can use Graphics View together with
+ embedded widgets and Qt's \l{State Machine Framework} to create a simple
+ but useful, dynamic, animated user interface.
\image padnavigator-example.png
+
+ The interface consists of a flippable, rotating pad with icons that can be
+ selected using the arrow keys on your keyboard or keypad. Pressing enter
+ will flip the pad around and reveal its back side, which has a form
+ embedded into a QGraphicsProxyWidget. You can interact with the form, and
+ press the enter key to flip back to the front side of the pad at any time.
+
+ Graphics View provides the QGraphicsScene class for managing and
+ interacting with a large number of custom-made 2D graphical items derived
+ from the QGraphicsItem class, and a QGraphicsView widget for visualizing
+ the items, with support for zooming and rotation.
+
+ This example consists of a \c RoundRectItem class, a \c FlippablePad class,
+ a \c PadNavigator class, a \c SplashItem class, and a \c main() function.
+
+ \section1 RoundRectItem Class Definition
+
+ The \c RoundRectItem class is used by itself to diplay the icons on the
+ pad, and as a base class for \c FlippablePad, the class for the pad itself.
+ The role of the class is to paint a round rectangle of a specified size and
+ gradient color, and optionally to paint a pixmap icon on top. To support \c
+ FlippablePad it also allows filling its contents with a plain window
+ background color.
+
+ Let's start by reviewing the \c RoundRectItem class declaration.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.h 0
+
+ \c RoundRectItem inherits QGraphicsObject, which makes it easy to control
+ its properties using QPropertyAnimation. Its constructor takes a rectangle
+ to determine its bounds, and a color.
+
+ Besides implementing the mandatory \l{QGraphicsItem::paint()}{paint()} and
+ \l{QGraphicsItem::boundingRect()}{boundingRect()} pure virtual functions,
+ it also provides the \c pixmap and \c fill properties.
+
+ The \c pixmap property sets an optional pixmap that is drawn on top of the
+ round rectangle. The \c fill property will, when true, fill the round
+ rectangle contents with a fixed QPalette::Window background color.
+ Otherwise the contents are filled using a gradient based on the color
+ passed to \c RoundRectItem's constructor.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.h 1
+
+ The private data members are:
+
+ \list
+ \o \c pix: The optional pixmap that is drawn on top of the rectangle.
+ \o \c fillRect: Corresponds to the \c fill property.
+ \o \c color: The configurable gradient color fill of the rectangle.
+ \o \c bounds: The bounds of the rectangle.
+ \o \c gradient: A precalculated gradient used to fill the rectangle.
+ \endlist
+
+ We will now review the \c RoundRectItem implementation. Let's start by
+ looking at its constructor:
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.cpp 0
+
+ The constructor initializes its member variables and forwards the \c parent
+ argument to QGraphicsObject's constructor. It then constructs the linear
+ gradient that is used in \l{QGraphicsItem::paint()}{paint()} to draw the
+ round rectangle's gradient background. The linear gradient's starting point
+ is at the top-left corner of the bounds, and the end is at the bottom-left
+ corner. The start color is identical to the color passed as an argument,
+ and a slightly darker color is chosen for the final stop.
+
+ We store this gradient as a member variable to avoid having to recreate the
+ gradient every time the item is repainted.
+
+ Finally we set the cache mode
+ \l{QGraphicsItem::ItemCoordinateCache}{ItemCoordinateCache}. This mode
+ causes the item's rendering to be cached into an off-screen pixmap that
+ remains persistent as we move and transform the item. This mode is ideal
+ for this example, and works particularily well with OpenGL and OpenGL ES.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.cpp 1
+
+ The \c pixmap property implementation simple returns the member pixmap, or
+ sets it and then calls \l{QGraphicsItem::update()}{update()}.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.cpp 2
+
+ As the \l{QGraphicsItem::paint()}{paint()} implementation below draws a
+ simple drop shadow down and to the right of the item, we return a slightly
+ adjusted rectangle from \l{QGraphicsItem::boundingRect()}{boundingRect()}.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.cpp 3
+
+ The \l{QGraphicsItem::paint()}{paint()} implementation starts by rendering
+ a semi transparent black round rectangle drop shadow, two units down and to
+ the right of the main item.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.cpp 4
+
+ We then draw the "foreground" round rectangle itself. The fill depends on
+ the \c fill property; if true, we will with a plain QPalette::Window color.
+ We get the corrent brush from QApplication::palette(). We assign a single
+ unit wide pen for the stroke, assign the brush, and then draw the
+ rectangle.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.cpp 5
+
+ If a pixmap has been assigned to the \e pixmap property, we draw this
+ pixmap in the center of the rectangle item. The pixmaps are scaled to match
+ the size of the icons; in arguably a better approach would have been to
+ store the icons with the right size in the first places.
+
+ \snippet examples/graphicsview/padnavigator/roundrectitem.cpp 6
+
+ Finally, for completeness we include the \c fill property implementation.
+ It returns the \c fill member variable's value, and when assigned to, it
+ calls \l{QGraphicsItem::update()}{update()}.
+
+ As mentioned already, \c RoundRectItem is the base class for \c
+ FlippablePad, which is the class representing the tilting pad itself. We
+ will proceed to reviewing \c FlippablePad.
+
+ \section1 FlippablePad Class Definition
+
+ \c FlippablePad is, in addition to its inherited \c RoundRectItem
+ responsibilities, responsible for creating and managing a grid of icons.
+
+ \snippet examples/graphicsview/padnavigator/flippablepad.h 0
+
+ Its declaration is very simple: It inherits \c RoundRectItem and does not
+ need any special polymorphic behavior. It's suitable to declare its own
+ constructor, and a getter-function that allows \c PadNavigator to access
+ the icons in the grid by (row, column).
+
+ The example has no "real" behavior or logic of any kind, and because of
+ that, the icons do not need to provide any \e behavior or special
+ interactions management. In a real application, however, it would be
+ natural for the \c FlippablePad and its icons to handle more of the
+ navigation logic. In this example, we have chosen to leave this to
+ the \c PadNavigator class, which we will get back to below.
+
+ We will now review the \c FlippablePad implementation. This implementation
+ starts with two helper functions: \c boundsFromSize() and \c
+ posForLocation():
+
+ \snippet examples/graphicsview/padnavigator/flippablepad.cpp 0
+
+ \c boundsForSize() takes a QSize argument, and returns the bounding
+ rectangle of the flippable pad item. The QSize determines how many rows and
+ columns the icon grid should have. Each icon is given 150x150 units of
+ space, and this determines the bounds.
+
+ \snippet examples/graphicsview/padnavigator/flippablepad.cpp 1
+
+ \c posForLocation() returns the position of an icon given its row and
+ column position. Like \c boundsForSize(), the function assumes each icon is
+ given 150x150 units of space, and that all icons are centered around the
+ flippable pad item's origin (0, 0).
+
+ \snippet examples/graphicsview/padnavigator/flippablepad.cpp 2
+
+ The \c FlippablePad constructor passes suitable bounds (using \c
+ boundsForSize()) and specific color to \c RoundRectItem's constructor.
+
+ \snippet examples/graphicsview/padnavigator/flippablepad.cpp 3
+
+ It then loads pixmaps from compiled-in resources to use for its icons.
+ QDirIterator is very useful in this context, as it allows us to fetch all
+ resource "*.png" files inside the \c :/images directory without explicitly
+ naming the files.
+
+ We also make sure not to load more pixmaps than we need.
+
+ \snippet examples/graphicsview/padnavigator/flippablepad.cpp 4
+
+ Now that we have the pixmaps, we can create icons, position then and assign
+ pixmaps. We start by finding a suitable size and color for the icons, and
+ initializing a convenient grid structure for storing the icons. This \c
+ iconGrid is also used later to find the icon for a specific (column, row)
+ location.
+
+ For each row and column in our grid, we proceed to constructing each icon
+ as an instance of \c RoundRectItem. The item is placed by using the \c
+ posForLocation() helper function. To make room for the slip-behind
+ selection item, we give each icon a \l{QGraphicsItem::zValue()}{Z-value} of
+ 1. The pixmaps are distributed to the icons in round-robin fasion.
+
+ Again, this approach is only suitable for example purposes. In a real-life
+ application where each icon represents a specific action, it would be more
+ natural to assign the pixmaps directly, or that the icons themselves
+ provide suitable pixmaps.
+
+ \snippet examples/graphicsview/padnavigator/flippablepad.cpp 5
+
+ Finally, the \c iconAt() function returns a pointer to the icon at a
+ specific row and column. It makes a somewhat bold assumption that the input
+ is valid, which is fair because the \c PadNavigator class only calls this
+ function with correct input.
+
+ We will now review the \c SplashItem class.
+
+ \section1 SplashItem Class Definition
+
+ The \c SplashItem class represents the "splash window", a semitransparent
+ white overlay with text that appears immediately after the application has
+ started, and disappears after pressing any key. The animation is controlled
+ by \c PadNavigator; this class is very simple by itself.
+
+ \snippet examples/graphicsview/padnavigator/splashitem.h 0
+
+ The class declaration shows that \c SplashItem inherits QGraphicsObject to
+ allow it to be controlled by QPropertyAnimation. It reimplements the
+ mandatory \l{QGraphicsItem::paint()}{paint()} and
+ \l{QGraphicsItem::boundingRect()}{boundingRect()} pure virtual functions,
+ and keeps a \c text member variable which will contain the information text
+ displayed on this splash item.
+
+ Let's look at its implementation.
+
+ \snippet examples/graphicsview/padnavigator/splashitem.cpp 0
+
+ The constructor forwards to QGraphicsObject as expected, assigns a text
+ message to the \c text member variable, and enables
+ \l{QGraphicsItem::DeviceCoordinateCache}{DeviceCoordinateCache}. This cache
+ mode is suitable because the splash item only moves and is never
+ transformed, and because it contains text, it's important that it has a
+ pixel perfect visual appearance (in constrast to
+ \l{QGraphicsItem::ItemCoordinateCache}{ItemCoordinateCache}, where the
+ visual appearance is not as good).
+
+ We use caching to avoid having to relayout and rerender the text for each
+ frame. An alterative approach would be to use the new QStaticText class.
+
+ \snippet examples/graphicsview/padnavigator/splashitem.cpp 1
+
+ \c SplashItem's bounding rectangle is fixed at (400x175).
+
+ \snippet examples/graphicsview/padnavigator/splashitem.cpp 2
+
+ The \l{QGraphicsItem::paint()}{paint()} implementation draws a clipped
+ round rectangle with a thick 2-unit border and a semi-transparent white
+ background. It proceeds to finding a suitable text area by adjusting the
+ splash item's bounding rectangle with 10 units in each side. The text is
+ rendered inside this rectangle, with top-left alignment, and with word
+ wrapping enabled.
+
+ The main class now remains. We will proceed to reviewing \c PadNavigator.
+
+ \section1 PadNavigator Class Definition
+
+ \c PadNavigator represents the main window of our Pad Navigator Example
+ application. It creates and controls a somewhat complex state machine, and
+ several animations. Its class declaration is very simple:
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.h 0
+
+ It inherits QGraphicsView and reimplements only one function:
+ \l{QGraphicsView::resizeEvent()}{resizeEvent()}, to ensure the scene is
+ scaled to fit inside the view when resizing the main window.
+
+ The \c PadNavigator constructor takes a QSize argument that determines the
+ number or rows and columns in the grid.
+
+ It also keeps a private member instance, \c form, which is the generated
+ code for the pad's back side item's QGraphicsProxyWidget-embedded form.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 0
+
+ \c PadNavigator's constructor is a bit long. In short, its job is to create
+ all items, including the \c FlippablePad, the \c SplashItem and the
+ QGraphicsProxyWidget \c backItem, and then to set up all animations, states
+ and transitions that control the behavior of the application.
+
+ It starts out simple, by forwarding to QGraphicsView's constructor.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 1
+
+ The first item to be created is \c SplashItem. This is going to be a top-level
+ item in the scene, next to \c FlippablePad, and stacked on top of it, so we
+ assign it a \l{QGraphicsItem::zValue()}{Z-value} of 1.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 2
+
+ Now we construct the \c FlippablePad item, passing its column-row count to
+ its constructor.
+
+ The pad is constrolled by three transformations, and we create one
+ QGraphicsRotation object for each of these.
+
+ \list
+ \o \c flipRotation: Rotates the grid around its Qt::YAxis. This rotation is
+ animated from 0 to 180, and eventually back, when enter is pressed on the
+ keyboard, flipping the pad around.
+ \o \c xRotation: Rotates the grid around its Qt::XAxis. This is used to
+ tilt the pad vertically corresponding to which item is currently selected.
+ This way, the selected item is always kept in front.
+ \o \c yRotation: Rotates the grid around its Qt::YAxis. This is used to
+ tilt the pad horizontally corresponding to which item is selected. This
+ way, the selected item is always kept in front.
+ \endlist
+
+ The combination of all three rotations is assigned via
+ QGraphicsItem::setTransformations().
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 3
+
+ Now we construct the QGraphicsProxyWidget-embedded \c backItem. The proxy
+ widget is created as a child of the pad. We create a new QWidget and
+ populate it with the \c form member. To ensure the \c hostName line edit is
+ the first to receive input focus when this item is shown, we call
+ \l{QWidget::setFocus()}{setFocus()} immediately. This will not give the
+ widget focus right away; it will only prepare the item to automatically
+ receive focus once it is shown.
+
+ The QWidget based form is embedded into the proxy widget. The proxy is
+ hidden initially; we only want to show it when the pad is rotated at least
+ 90 degrees, and we also rotate the proxy itself by 180 degrees. This way we
+ give the impression that the proxy widget is "behind" the flipped pad, when
+ in fact, it's actually \e{on top of it}.
+
+ We enable \l{QGraphicsItem::ItemCoordinateCache}{ItemCoordinateCache} to
+ ensure the flip animation can run smoothly.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 4
+
+ We now create the selection item. This is simply another instance of \c
+ RoundRectItem that is slightly larger than the icons on the pad. We create
+ it as an immediate child of the \c FlippablePad, so the selection item is a
+ sibling to all the icons. By giving it a
+ \l{QGraphicsItem::zValue()}{Z-value} of 0.5 we ensure it will slide beteen
+ the pad and its icons.
+
+ What follows now is a series of animation initializations.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 5
+
+ We begin with the animations that apply to the splash item. The first
+ animation, \c smoothSplashMove, ensures that the "y" property of \c splash
+ will be animated with a 250-millisecond duration
+ \l{QEasingCurve::InQuad}{InQuad} easing function. \c smoothSplashOpacity
+ ensures the opacity of \c splash eases in and out in 250 milliseconds.
+
+ The values are assigned by \c PadNavigator's state machine, which is
+ created later.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 6
+
+ These are the animations that control the selection item's movement and the
+ \c xRotation and \c yRotation QGraphicsRotation objects that tilt the pad.
+ All animations have a duration of 125 milliseconds, and they all use the
+ \l{QEasingCurve::InOutQuad}{InOutQuad} easing function.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 7
+
+ We now create the animations that control the flip-effect when you press
+ the enter key. The main goal is to rotate the pad by 180 degrees or back,
+ but we also need to make sure the selection item's tilt rotations are reset
+ back to 0 when the pad is flipped, and restored back to their original
+ values when flipped back:
+
+ \list
+ \o \c smoothFlipRotation: Animates the main 180 degree rotation of the pad.
+ \o \c smoothFlipScale: Scales the pad out and then in again while the pad is rotating.
+ \o \c smoothFlipXRotation: Animates the selection item's X-tilt to 0 and back.
+ \o \c smoothFlipYRotation: Animates the selection item's Y-tilt to 0 and back.
+ \o \c flipAnimation: A parallel animation group that ensures all the above animations are run in parallel.
+ \endlist
+
+ All animations are given a 500 millisecond duration and an
+ \l{QEasingCurve::InOutQuad}{InOutQuad} easing function.
+
+ It's worth taking a close look at \c smoothFlipScale. This animation's
+ start and end values are both 1.0, but at animation step 0.5 the
+ animation's value is 0.7. This means that after 50% of the animation's
+ duration, or 250 milliseconds, the pad will be scaled down to 0.7x of its
+ original size, which gives a great visual effect while flipping.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 8
+
+ This section uses a trick to ensure that certain properties are assigned
+ precisely when the flip animation passes 50%, or 90 degrees, rotation. In
+ short, the pad's icons and selection item are all hidden, the pad's \c fill
+ property is enabled, and \c backItem is shown when flipping over. When
+ flipping back, the reverse properties are applied.
+
+ The way this is achieved is by running a sequential animation in parallel
+ to the other animations. This sequence, dubbed \c setVariablesSequence,
+ starts with a 250 millisecond pause, and then executes several animations
+ with a duration of 0. Each animation will ensure that properties are set
+ immediate at this point.
+
+ This approach can also be used to call functions or set any other
+ properties at a specific time while an animation is running.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 9
+
+ We will now create the state machine. The whole \c PadNavigator state
+ machinery is controlled by one single state machine that has a
+ straight-forward state structure. The state engine itself is created
+ as a child of the \c PadNavigator itself. We then create three top level
+ states:
+
+ \list
+ \o \c splashState: The initial state where the splash item is visible.
+ \o \c frontState: The base state where the splash is gone and we can see
+ the front side of the pad, and navigate the selection item.
+ \o \c backState: The flipped state where the \c backItem is visible, and we
+ can interact with the QGraphicsProxyWidget-embedded form.
+ \endlist
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 10
+
+ Each state assigns specific properties to objects on entry. Most
+ interesting perhaps is the assignment of the value 0.0 to the pad's \c
+ flipRotation angle property when in \c frontState, and 180.0 when in \c
+ backState. At the end of this section we register default animations with
+ the state engine; these animations will apply to their respective objects
+ and properties for any state transition. Otherwise it's common to assign
+ animations to specific transitions.
+
+ The \c splashState state is set as the initial state. This is required
+ before we start the state engine. We proceed with creating some
+ transitions.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 11
+
+ QEventTransition defines a very flexible transition type. You can use this
+ class to trigger a transition based on an object receiving an event of a
+ specific type. In this case, we would like to transition from \c
+ splashState into \c frontState if \c PadNavigator receives any key press
+ event (QEvent::KeyPress).
+
+ We register the \c splashItem's animations to this transition to ensure they
+ are used to animate the item's movement and opacity.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 12
+
+ We use QKeyEventTransition to capture specific key events. In this case, we
+ detect that the user presses Qt::Key_Return or Qt::Key_Enter, and use this
+ to trigger transitions between \c frontState and backState. We register \c
+ flipAnimation, our complex parallel animation group, with these
+ transitions.
+
+ We continue by defining the states for each of the icons in the grid.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 13
+
+ We will use state groups to control transitions between icons. Each icon
+ represents a \e substate of \c frontState. We will then define transitions
+ between the states by detecting key presses, using QKeyEventTransition.
+
+ We start by creating all the substates, and at the same time we create a
+ temporary grid structure for the states to make it easier to find which
+ states represents icons that are up, down, left and to the right each
+ other.
+
+ Once the first substate is known, we set this up as the initial substate of
+ \c frontState. We will use the (0, 0), or top-left, icon for the initial
+ substate. We initialze the selection item's position to be exactly where
+ the top-left icon is.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 14
+
+ We can now create four transitions for each icon. Each transition ensures
+ that we move to the state corresponding to which arrow key has been
+ pressed. It's clear from this techinique that we could design any other
+ specific transitions to and from each of the sub states depending on these
+ and other keys.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 15
+
+ Also, for each of the icons, we assign suitable values to the \c xRotation
+ and \c yRotation objects' "angle"-properties. If you recall, these
+ properties "tilt" the pad corresponding to which item is currently
+ selected. We ensure each icon is invisible when the pad is flipped, and
+ visible when the pad is not flipped. To ensure the visible property is
+ assigned at the right time, we add property-controlling animations to the
+ \c setVariableSequence animation defined earlier.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 16
+
+ We are now finished with all states, transitions, and animations. We now
+ create the scene that will contain all our items. The scene gets a defined
+ background pixmap, and we disable item indexing (as most items in this
+ scene are animated). We add our \c pad item to the scene, and use its
+ bounding rectangle to fixate the scene rectangle. This rectangle is used by
+ the view to find a suitable size for the application window.
+
+ Then the scene is assigned to the view, or in our case, \c PadNavigator
+ itself.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 17
+
+ Now that the scene has received its final size, we can position the splash
+ item at the very top, find its fade-out position, and add it to the scene.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 18
+
+ The view toggles a few necessary properties:
+
+ \list
+ \o It disables its scroll bars - this application has no use for scroll bars.
+ \o It assigns a minimum size. This is necessary to avoid numerical errors
+ in our fit-in-view \c resizeEvent() implementation.
+ \o It sets \l{QGraphicsView::FullViewportUpdate}{FullViewportUpdate}, to
+ ensure QGraphicsView doesn't spend time figuring out precisely what needs
+ to be redrawn. This application is very simple - if anything changes,
+ everything is updated.
+ \o It enables background caching - this makes no performance difference
+ with OpenGL, but without OpenGL it avoids unnecessary re-scaling of the
+ background pixmap.
+ \o It sets render hints that increase rendering quality.
+ \o If OpenGL is supported, a QGLWidget viewport is assigned to the view.
+ \endlist
+
+ Finally, we start the state engine.
+
+ \snippet examples/graphicsview/padnavigator/padnavigator.cpp 19
+
+ The \l{QGraphicsView::resizeEvent()}{resizeEvent()} implementation calls
+ the base implementation, and then calls QGraphicsView::fitInView() to scale
+ the scene so that it fits perfectly inside the view.
+
+ By resizing the main application window, you can see this effect yourself.
+ The scene contents grow when you make the window larger, and shrink when
+ you make it smaller, while keeping the aspect ratio intact.
+
+ \section1 The main() Function
+
+ \snippet examples/graphicsview/padnavigator/main.cpp 0
+
+ The \c main function creates the QApplication instance, uses
+ Q_INIT_RESOURCE to ensure our compiled-in resources aren't removed by the
+ linker, and then creates a 3x3 \c PadNavigator instance and shows it.
+
+ Our flippable pad shows up with a suitable splash item once control returns
+ to the event loop.
+
+ \section1 Performance Notes
+
+ The example uses OpenGL if this is available, to achieve optimal
+ performance; otherwise perspective tranformations can be quite costly.
+
+ Although this example does use QGraphicsProxyWidget to demonstrate
+ integration of Qt widget components integrated into Graphics View, using
+ QGraphicsProxyWidget comes with a performance penalty, and is therefore not
+ recommended for embedded development.
+
+ This example uses extensive item caching to avoid rerendering of static
+ elements, at the expense of graphics memory.
*/
diff --git a/doc/src/getting-started/examples.qdoc b/doc/src/getting-started/examples.qdoc
index 542f672..f511cd6 100644
--- a/doc/src/getting-started/examples.qdoc
+++ b/doc/src/getting-started/examples.qdoc
@@ -651,6 +651,7 @@
\o \l{graphicsview/diagramscene}{Diagram Scene}\raisedaster
\o \l{graphicsview/dragdroprobot}{Drag and Drop Robot}\raisedaster
\o \l{graphicsview/elasticnodes}{Elastic Nodes}\raisedaster
+ \o \l{graphicsview/padnavigator}{Pad Navigator}\raisedaster
\o \l{graphicsview/portedasteroids}{Ported Asteroids}
\o \l{graphicsview/portedcanvas}{Ported Canvas}
\endlist
diff --git a/examples/graphicsview/padnavigator/flippablepad.cpp b/examples/graphicsview/padnavigator/flippablepad.cpp
index 61f421f..58aea00 100644
--- a/examples/graphicsview/padnavigator/flippablepad.cpp
+++ b/examples/graphicsview/padnavigator/flippablepad.cpp
@@ -43,37 +43,43 @@
#include <QtGui/QtGui>
+//! [0]
static QRectF boundsFromSize(const QSize &size)
{
return QRectF((-size.width() / 2.0) * 150, (-size.height() / 2.0) * 150,
size.width() * 150, size.height() * 150);
}
+//! [0]
-static QPointF posForLocation(int x, int y, const QSize &size)
+//! [1]
+static QPointF posForLocation(int column, int row, const QSize &size)
{
- return QPointF(x * 150, y * 150)
+ return QPointF(column * 150, row * 150)
- QPointF((size.width() - 1) * 75, (size.height() - 1) * 75);
}
+//! [1]
+//! [2]
FlippablePad::FlippablePad(const QSize &size, QGraphicsItem *parent)
: RoundRectItem(boundsFromSize(size), QColor(226, 255, 92, 64), parent)
{
- columns = size.width();
-
+//! [2]
+//! [3]
int numIcons = size.width() * size.height();
QList<QPixmap> pixmaps;
QDirIterator it(":/images", QStringList() << "*.png");
while (it.hasNext() && pixmaps.size() < numIcons)
pixmaps << it.next();
+//! [3]
+//! [4]
const QRectF iconRect(-54, -54, 108, 108);
const QColor iconColor(214, 240, 110, 128);
-
iconGrid.resize(size.height());
-
int n = 0;
+
for (int y = 0; y < size.height(); ++y) {
- iconGrid[y].resize(columns);
+ iconGrid[y].resize(size.width());
for (int x = 0; x < size.width(); ++x) {
RoundRectItem *rect = new RoundRectItem(iconRect, iconColor, this);
rect->setZValue(1);
@@ -83,8 +89,11 @@ FlippablePad::FlippablePad(const QSize &size, QGraphicsItem *parent)
}
}
}
+//! [4]
-RoundRectItem *FlippablePad::iconAt(int x, int y) const
+//! [5]
+RoundRectItem *FlippablePad::iconAt(int column, int row) const
{
- return iconGrid[y][x];
+ return iconGrid[row][column];
}
+//! [5]
diff --git a/examples/graphicsview/padnavigator/flippablepad.h b/examples/graphicsview/padnavigator/flippablepad.h
index 9adb18b..7d99536 100644
--- a/examples/graphicsview/padnavigator/flippablepad.h
+++ b/examples/graphicsview/padnavigator/flippablepad.h
@@ -48,16 +48,17 @@
#include <QLinearGradient>
#include <QVector>
+//! [0]
class FlippablePad : public RoundRectItem
{
public:
FlippablePad(const QSize &size, QGraphicsItem *parent = 0);
- RoundRectItem *iconAt(int x, int y) const;
+ RoundRectItem *iconAt(int column, int row) const;
private:
- int columns;
QVector<QVector<RoundRectItem *> > iconGrid;
};
+//! [0]
#endif // FLIPPABLEPAD_H
diff --git a/examples/graphicsview/padnavigator/main.cpp b/examples/graphicsview/padnavigator/main.cpp
index 6d148bb..984b976 100644
--- a/examples/graphicsview/padnavigator/main.cpp
+++ b/examples/graphicsview/padnavigator/main.cpp
@@ -43,6 +43,7 @@
#include <QtGui/QtGui>
+//! [0]
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
@@ -53,3 +54,4 @@ int main(int argc, char *argv[])
return app.exec();
}
+//! [0]
diff --git a/examples/graphicsview/padnavigator/padnavigator.cpp b/examples/graphicsview/padnavigator/padnavigator.cpp
index 456b3f4..b1d19f6 100644
--- a/examples/graphicsview/padnavigator/padnavigator.cpp
+++ b/examples/graphicsview/padnavigator/padnavigator.cpp
@@ -42,175 +42,213 @@
#include "flippablepad.h"
#include "padnavigator.h"
#include "splashitem.h"
-#include "ui_form.h"
#include <QtGui/QtGui>
#ifndef QT_NO_OPENGL
#include <QtOpenGL/QtOpenGL>
#endif
+//! [0]
PadNavigator::PadNavigator(const QSize &size, QWidget *parent)
: QGraphicsView(parent)
{
- // Prepare splash item
+//! [0]
+//! [1]
+ // Splash item
SplashItem *splash = new SplashItem;
splash->setZValue(1);
+//! [1]
- // Prepare pad item
+//! [2]
+ // Pad item
FlippablePad *pad = new FlippablePad(size);
QGraphicsRotation *flipRotation = new QGraphicsRotation(pad);
- flipRotation->setAxis(Qt::YAxis);
QGraphicsRotation *xRotation = new QGraphicsRotation(pad);
- xRotation->setAxis(Qt::YAxis);
QGraphicsRotation *yRotation = new QGraphicsRotation(pad);
+ flipRotation->setAxis(Qt::YAxis);
+ xRotation->setAxis(Qt::YAxis);
yRotation->setAxis(Qt::XAxis);
pad->setTransformations(QList<QGraphicsTransform *>()
<< flipRotation
<< xRotation << yRotation);
+//! [2]
- // Prepare backitem
- form = new Ui_Form;
- QWidget *widget = new QWidget;
- form->setupUi(widget);
- form->hostName->setFocus();
+//! [3]
+ // Back (proxy widget) item
QGraphicsProxyWidget *backItem = new QGraphicsProxyWidget(pad);
- backItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ QWidget *widget = new QWidget;
+ form.setupUi(widget);
+ form.hostName->setFocus();
backItem->setWidget(widget);
+ backItem->setVisible(false);
+ backItem->setFocus();
+ backItem->setCacheMode(QGraphicsItem::ItemCoordinateCache);
+ const QRectF r = backItem->rect();
backItem->setTransform(QTransform()
.rotate(180, Qt::YAxis)
- .translate(-backItem->rect().width()/2, -backItem->rect().height()/2));
- backItem->setFocus();
- backItem->setVisible(false);
+ .translate(-r.width()/2, -r.height()/2));
+//! [3]
- // Prepare selection item
+//! [4]
+ // Selection item
RoundRectItem *selectionItem = new RoundRectItem(QRectF(-60, -60, 120, 120),
Qt::gray, pad);
selectionItem->setZValue(0.5);
+//! [4]
- // Selection animation setup
+//! [5]
+ // Splash animations
+ QPropertyAnimation *smoothSplashMove = new QPropertyAnimation(splash, "y");
+ QPropertyAnimation *smoothSplashOpacity = new QPropertyAnimation(splash, "opacity");
+ smoothSplashMove->setEasingCurve(QEasingCurve::InQuad);
+ smoothSplashMove->setDuration(250);
+ smoothSplashOpacity->setDuration(250);
+//! [5]
+
+//! [6]
+ // Selection animation
QPropertyAnimation *smoothXSelection = new QPropertyAnimation(selectionItem, "x");
- smoothXSelection->setDuration(125);
- smoothXSelection->setEasingCurve(QEasingCurve::InOutQuad);
QPropertyAnimation *smoothYSelection = new QPropertyAnimation(selectionItem, "y");
- smoothYSelection->setDuration(125);
- smoothYSelection->setEasingCurve(QEasingCurve::InOutQuad);
QPropertyAnimation *smoothXRotation = new QPropertyAnimation(xRotation, "angle");
- smoothXRotation->setDuration(125);
- smoothXRotation->setEasingCurve(QEasingCurve::InOutQuad);
QPropertyAnimation *smoothYRotation = new QPropertyAnimation(yRotation, "angle");
+ smoothXSelection->setDuration(125);
+ smoothYSelection->setDuration(125);
+ smoothXRotation->setDuration(125);
smoothYRotation->setDuration(125);
+ smoothXSelection->setEasingCurve(QEasingCurve::InOutQuad);
+ smoothYSelection->setEasingCurve(QEasingCurve::InOutQuad);
+ smoothXRotation->setEasingCurve(QEasingCurve::InOutQuad);
smoothYRotation->setEasingCurve(QEasingCurve::InOutQuad);
- QPropertyAnimation *smoothScale = new QPropertyAnimation(pad, "scale");
- smoothScale->setDuration(500);
- smoothScale->setKeyValueAt(0, qVariantValue<qreal>(1.0));
- smoothScale->setKeyValueAt(0.5, qVariantValue<qreal>(0.7));
- smoothScale->setKeyValueAt(1, qVariantValue<qreal>(1.0));
- smoothScale->setEasingCurve(QEasingCurve::InOutQuad);
+//! [6]
+//! [7]
// Flip animation setup
QPropertyAnimation *smoothFlipRotation = new QPropertyAnimation(flipRotation, "angle");
+ QPropertyAnimation *smoothFlipScale = new QPropertyAnimation(pad, "scale");
+ QPropertyAnimation *smoothFlipXRotation = new QPropertyAnimation(xRotation, "angle");
+ QPropertyAnimation *smoothFlipYRotation = new QPropertyAnimation(yRotation, "angle");
+ QParallelAnimationGroup *flipAnimation = new QParallelAnimationGroup(this);
+ smoothFlipScale->setDuration(500);
smoothFlipRotation->setDuration(500);
+ smoothFlipXRotation->setDuration(500);
+ smoothFlipYRotation->setDuration(500);
+ smoothFlipScale->setEasingCurve(QEasingCurve::InOutQuad);
smoothFlipRotation->setEasingCurve(QEasingCurve::InOutQuad);
- QPropertyAnimation *flipSmoothXRotation = new QPropertyAnimation(xRotation, "angle");
- flipSmoothXRotation->setDuration(500);
- flipSmoothXRotation->setEasingCurve(QEasingCurve::InOutQuad);
- QPropertyAnimation *flipSmoothYRotation = new QPropertyAnimation(yRotation, "angle");
- flipSmoothYRotation->setDuration(500);
- flipSmoothYRotation->setEasingCurve(QEasingCurve::InOutQuad);
- QPropertyAnimation *setBackItemVisibleAnim = new QPropertyAnimation(backItem, "visible");
- setBackItemVisibleAnim->setDuration(0);
- QPropertyAnimation *setSelectionItemVisibleAnim = new QPropertyAnimation(selectionItem, "visible");
- setSelectionItemVisibleAnim->setDuration(0);
- QPropertyAnimation *setFillAnim = new QPropertyAnimation(pad, "fill");
- setFillAnim->setDuration(0);
- QSequentialAnimationGroup *setVisibleAnimation = new QSequentialAnimationGroup;
- setVisibleAnimation->addPause(250);
- setVisibleAnimation->addAnimation(setBackItemVisibleAnim);
- setVisibleAnimation->addAnimation(setSelectionItemVisibleAnim);
- setVisibleAnimation->addAnimation(setFillAnim);
- QParallelAnimationGroup *flipAnimation = new QParallelAnimationGroup(this);
+ smoothFlipXRotation->setEasingCurve(QEasingCurve::InOutQuad);
+ smoothFlipYRotation->setEasingCurve(QEasingCurve::InOutQuad);
+ smoothFlipScale->setKeyValueAt(0, qVariantValue<qreal>(1.0));
+ smoothFlipScale->setKeyValueAt(0.5, qVariantValue<qreal>(0.7));
+ smoothFlipScale->setKeyValueAt(1, qVariantValue<qreal>(1.0));
flipAnimation->addAnimation(smoothFlipRotation);
- flipAnimation->addAnimation(smoothScale);
- flipAnimation->addAnimation(flipSmoothXRotation);
- flipAnimation->addAnimation(flipSmoothYRotation);
- flipAnimation->addAnimation(setVisibleAnimation);
+ flipAnimation->addAnimation(smoothFlipScale);
+ flipAnimation->addAnimation(smoothFlipXRotation);
+ flipAnimation->addAnimation(smoothFlipYRotation);
+//! [7]
- QPropertyAnimation *smoothSplashMove = new QPropertyAnimation(splash, "y");
- smoothSplashMove->setEasingCurve(QEasingCurve::InQuad);
- smoothSplashMove->setDuration(250);
- QPropertyAnimation *smoothSplashOpacity = new QPropertyAnimation(splash, "opacity");
- smoothSplashOpacity->setDuration(250);
+//! [8]
+ // Flip animation delayed property assignment
+ QSequentialAnimationGroup *setVariablesSequence = new QSequentialAnimationGroup;
+ QPropertyAnimation *setFillAnimation = new QPropertyAnimation(pad, "fill");
+ QPropertyAnimation *setBackItemVisibleAnimation = new QPropertyAnimation(backItem, "visible");
+ QPropertyAnimation *setSelectionItemVisibleAnimation = new QPropertyAnimation(selectionItem, "visible");
+ setFillAnimation->setDuration(0);
+ setBackItemVisibleAnimation->setDuration(0);
+ setSelectionItemVisibleAnimation->setDuration(0);
+ setVariablesSequence->addPause(250);
+ setVariablesSequence->addAnimation(setBackItemVisibleAnimation);
+ setVariablesSequence->addAnimation(setSelectionItemVisibleAnimation);
+ setVariablesSequence->addAnimation(setFillAnimation);
+ flipAnimation->addAnimation(setVariablesSequence);
+//! [8]
+//! [9]
// Build the state machine
QStateMachine *stateMachine = new QStateMachine(this);
QState *splashState = new QState(stateMachine);
QState *frontState = new QState(stateMachine);
QHistoryState *historyState = new QHistoryState(frontState);
QState *backState = new QState(stateMachine);
+//! [9]
+//! [10]
+ frontState->assignProperty(pad, "fill", false);
frontState->assignProperty(splash, "opacity", 0.0);
- frontState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(0.0));
frontState->assignProperty(backItem, "visible", false);
+ frontState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(0.0));
frontState->assignProperty(selectionItem, "visible", true);
- frontState->assignProperty(pad, "fill", false);
- backState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(180.0));
+ backState->assignProperty(pad, "fill", true);
+ backState->assignProperty(backItem, "visible", true);
backState->assignProperty(xRotation, "angle", qVariantValue<qreal>(0.0));
backState->assignProperty(yRotation, "angle", qVariantValue<qreal>(0.0));
+ backState->assignProperty(flipRotation, "angle", qVariantValue<qreal>(180.0));
backState->assignProperty(selectionItem, "visible", false);
- backState->assignProperty(backItem, "visible", true);
- backState->assignProperty(pad, "fill", true);
stateMachine->addDefaultAnimation(smoothXRotation);
stateMachine->addDefaultAnimation(smoothYRotation);
stateMachine->addDefaultAnimation(smoothXSelection);
stateMachine->addDefaultAnimation(smoothYSelection);
stateMachine->setInitialState(splashState);
+//! [10]
+//! [11]
// Transitions
QEventTransition *anyKeyTransition = new QEventTransition(this, QEvent::KeyPress, splashState);
anyKeyTransition->setTargetState(frontState);
anyKeyTransition->addAnimation(smoothSplashMove);
anyKeyTransition->addAnimation(smoothSplashOpacity);
+//! [11]
- QKeyEventTransition *enterTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Enter, backState);
+//! [12]
+ QKeyEventTransition *enterTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Enter, backState);
+ QKeyEventTransition *returnTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Return, backState);
+ QKeyEventTransition *backEnterTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Enter, frontState);
+ QKeyEventTransition *backReturnTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Return, frontState);
enterTransition->setTargetState(historyState);
- QKeyEventTransition *returnTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Return, backState);
returnTransition->setTargetState(historyState);
- QKeyEventTransition *backEnterTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Enter, frontState);
backEnterTransition->setTargetState(backState);
- QKeyEventTransition *backReturnTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Return, frontState);
backReturnTransition->setTargetState(backState);
enterTransition->addAnimation(flipAnimation);
returnTransition->addAnimation(flipAnimation);
backEnterTransition->addAnimation(flipAnimation);
backReturnTransition->addAnimation(flipAnimation);
+//! [12]
- // Substates, one for each icon
+//! [13]
+ // Create substates for each icon; store in temporary grid.
int columns = size.width();
int rows = size.height();
QVector< QVector< QState * > > stateGrid;
stateGrid.resize(rows);
for (int y = 0; y < rows; ++y) {
stateGrid[y].resize(columns);
- for (int x = 0; x < columns; ++x) {
- QState *state = new QState(frontState);
- stateGrid[y][x] = state;
- }
+ for (int x = 0; x < columns; ++x)
+ stateGrid[y][x] = new QState(frontState);
}
frontState->setInitialState(stateGrid[0][0]);
selectionItem->setPos(pad->iconAt(0, 0)->pos());
+//! [13]
+//! [14]
// Enable key navigation using state transitions
for (int y = 0; y < rows; ++y) {
for (int x = 0; x < columns; ++x) {
QState *state = stateGrid[y][x];
- QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Right, state);
+ QKeyEventTransition *rightTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Right, state);
+ QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Left, state);
+ QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Down, state);
+ QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress,
+ Qt::Key_Up, state);
rightTransition->setTargetState(stateGrid[y][(x + 1) % columns]);
- QKeyEventTransition *leftTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Left, state);
leftTransition->setTargetState(stateGrid[y][((x - 1) + columns) % columns]);
- QKeyEventTransition *downTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Down, state);
downTransition->setTargetState(stateGrid[(y + 1) % rows][x]);
- QKeyEventTransition *upTransition = new QKeyEventTransition(this, QEvent::KeyPress, Qt::Key_Up, state);
upTransition->setTargetState(stateGrid[((y - 1) + rows) % rows][x]);
-
+//! [14]
+//! [15]
RoundRectItem *icon = pad->iconAt(x, y);
state->assignProperty(xRotation, "angle", -icon->x() / 6.0);
state->assignProperty(yRotation, "angle", icon->y() / 6.0);
@@ -219,47 +257,51 @@ PadNavigator::PadNavigator(const QSize &size, QWidget *parent)
frontState->assignProperty(icon, "visible", true);
backState->assignProperty(icon, "visible", false);
- QPropertyAnimation *setVisibleAnim = new QPropertyAnimation(icon, "visible");
- setVisibleAnim->setDuration(0);
- setVisibleAnimation->addAnimation(setVisibleAnim);
+ QPropertyAnimation *setIconVisibleAnimation = new QPropertyAnimation(icon, "visible");
+ setIconVisibleAnimation->setDuration(0);
+ setVariablesSequence->addAnimation(setIconVisibleAnimation);
}
}
+//! [15]
- // Setup scene
+//! [16]
+ // Scene
QGraphicsScene *scene = new QGraphicsScene(this);
scene->setBackgroundBrush(QPixmap(":/images/blue_angle_swirl.jpg"));
scene->setItemIndexMethod(QGraphicsScene::NoIndex);
scene->addItem(pad);
scene->setSceneRect(scene->itemsBoundingRect());
setScene(scene);
+//! [16]
- // Adjust splash item
- splash->setPos(-splash->boundingRect().width() / 2, scene->sceneRect().top());
+//! [17]
+ // Adjust splash item to scene contents
+ const QRectF sbr = splash->boundingRect();
+ splash->setPos(-sbr.width() / 2, scene->sceneRect().top() - 2);
frontState->assignProperty(splash, "y", splash->y() - 100.0);
scene->addItem(splash);
+//! [17]
- // Setup view
+//! [18]
+ // View
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setMinimumSize(50, 50);
setViewportUpdateMode(FullViewportUpdate);
setCacheMode(CacheBackground);
- setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform
- | QPainter::TextAntialiasing);
+ setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing);
#ifndef QT_NO_OPENGL
setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers)));
#endif
stateMachine->start();
+//! [18]
}
-PadNavigator::~PadNavigator()
-{
- delete form;
-}
-
+//! [19]
void PadNavigator::resizeEvent(QResizeEvent *event)
{
QGraphicsView::resizeEvent(event);
fitInView(scene()->sceneRect(), Qt::KeepAspectRatio);
}
+//! [19]
diff --git a/examples/graphicsview/padnavigator/padnavigator.h b/examples/graphicsview/padnavigator/padnavigator.h
index c79a13c..03a1ea2 100644
--- a/examples/graphicsview/padnavigator/padnavigator.h
+++ b/examples/graphicsview/padnavigator/padnavigator.h
@@ -43,23 +43,25 @@
#define PADNAVIGATOR_H
#include <QGraphicsView>
+#include "ui_form.h"
class QState;
class QStateMachine;
class Ui_Form;
+//! [0]
class PadNavigator : public QGraphicsView
{
Q_OBJECT
public:
explicit PadNavigator(const QSize &size, QWidget *parent = 0);
- ~PadNavigator();
protected:
void resizeEvent(QResizeEvent *event);
private:
- Ui_Form *form;
+ Ui_Form form;
};
+//! [0]
#endif // PADNAVIGATOR_H
diff --git a/examples/graphicsview/padnavigator/roundrectitem.cpp b/examples/graphicsview/padnavigator/roundrectitem.cpp
index 2141e9a..7a0b279 100644
--- a/examples/graphicsview/padnavigator/roundrectitem.cpp
+++ b/examples/graphicsview/padnavigator/roundrectitem.cpp
@@ -43,34 +43,39 @@
#include <QtGui/QtGui>
+//! [0]
RoundRectItem::RoundRectItem(const QRectF &bounds, const QColor &color,
QGraphicsItem *parent)
- : QGraphicsObject(parent), fillRect(false), color(color), bounds(bounds)
+ : QGraphicsObject(parent), fillRect(false), bounds(bounds)
{
gradient.setStart(bounds.topLeft());
gradient.setFinalStop(bounds.bottomRight());
gradient.setColorAt(0, color);
gradient.setColorAt(1, color.dark(200));
-
setCacheMode(ItemCoordinateCache);
}
+//! [0]
+//! [1]
QPixmap RoundRectItem::pixmap() const
{
return pix;
}
-
void RoundRectItem::setPixmap(const QPixmap &pixmap)
{
pix = pixmap;
update();
}
+//! [1]
+//! [2]
QRectF RoundRectItem::boundingRect() const
{
return bounds.adjusted(0, 0, 2, 2);
}
+//! [2]
+//! [3]
void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
@@ -79,25 +84,31 @@ void RoundRectItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
painter->setPen(Qt::NoPen);
painter->setBrush(QColor(0, 0, 0, 64));
painter->drawRoundRect(bounds.translated(2, 2));
+//! [3]
+//! [4]
if (fillRect)
painter->setBrush(QApplication::palette().brush(QPalette::Window));
else
painter->setBrush(gradient);
painter->setPen(QPen(Qt::black, 1));
painter->drawRoundRect(bounds);
+//! [4]
+//! [5]
if (!pix.isNull()) {
painter->scale(1.95, 1.95);
painter->drawPixmap(-pix.width() / 2, -pix.height() / 2, pix);
}
}
+//! [5]
+//! [6]
bool RoundRectItem::fill() const
{
return fillRect;
}
-
void RoundRectItem::setFill(bool fill)
{
fillRect = fill;
update();
}
+//! [6]
diff --git a/examples/graphicsview/padnavigator/roundrectitem.h b/examples/graphicsview/padnavigator/roundrectitem.h
index ae5fb4c..bc58cec 100644
--- a/examples/graphicsview/padnavigator/roundrectitem.h
+++ b/examples/graphicsview/padnavigator/roundrectitem.h
@@ -45,6 +45,7 @@
#include <QGraphicsObject>
#include <QLinearGradient>
+//! [0]
class RoundRectItem : public QGraphicsObject
{
Q_OBJECT
@@ -61,13 +62,15 @@ public:
bool fill() const;
void setFill(bool fill);
+//! [0]
+//! [1]
private:
QPixmap pix;
bool fillRect;
- QColor color;
QRectF bounds;
QLinearGradient gradient;
};
+//! [1]
#endif // ROUNDRECTITEM_H
diff --git a/examples/graphicsview/padnavigator/splashitem.cpp b/examples/graphicsview/padnavigator/splashitem.cpp
index e609656..cd7074a 100644
--- a/examples/graphicsview/padnavigator/splashitem.cpp
+++ b/examples/graphicsview/padnavigator/splashitem.cpp
@@ -43,20 +43,25 @@
#include <QtGui/QtGui>
-SplashItem::SplashItem(QGraphicsItem *parent) :
- QGraphicsObject(parent)
+//! [0]
+SplashItem::SplashItem(QGraphicsItem *parent)
+ : QGraphicsObject(parent)
{
text = tr("Welcome to the Pad Navigator Example. You can use the"
" keyboard arrows to navigate the icons, and press enter"
" to activate an item. Press any key to begin.");
setCacheMode(DeviceCoordinateCache);
}
+//! [0]
+//! [1]
QRectF SplashItem::boundingRect() const
{
return QRectF(0, 0, 400, 175);
}
+//! [1]
+//! [2]
void SplashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
@@ -76,3 +81,4 @@ void SplashItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option
painter->setFont(font);
painter->drawText(textRect, flags, text);
}
+//! [2]
diff --git a/examples/graphicsview/padnavigator/splashitem.h b/examples/graphicsview/padnavigator/splashitem.h
index 9d57653..98c4a1f 100644
--- a/examples/graphicsview/padnavigator/splashitem.h
+++ b/examples/graphicsview/padnavigator/splashitem.h
@@ -44,6 +44,7 @@
#include <QGraphicsObject>
+//! [0]
class SplashItem : public QGraphicsObject
{
Q_OBJECT
@@ -56,5 +57,6 @@ public:
private:
QString text;
};
+//! [0]
#endif // SPLASHITEM_H