From 812f78e55aa3db4d51ec8617320358d80c4a71d5 Mon Sep 17 00:00:00 2001 From: Andreas Aardal Hanssen Date: Wed, 12 May 2010 16:32:12 +0200 Subject: Documentation for the Pad Navigator Example. This also does a few touch-ups on the source code. --- doc/src/examples/padnavigator.qdoc | 552 ++++++++++++++++++++- doc/src/getting-started/examples.qdoc | 1 + .../graphicsview/padnavigator/flippablepad.cpp | 27 +- examples/graphicsview/padnavigator/flippablepad.h | 5 +- examples/graphicsview/padnavigator/main.cpp | 2 + .../graphicsview/padnavigator/padnavigator.cpp | 218 ++++---- examples/graphicsview/padnavigator/padnavigator.h | 6 +- .../graphicsview/padnavigator/roundrectitem.cpp | 19 +- examples/graphicsview/padnavigator/roundrectitem.h | 5 +- examples/graphicsview/padnavigator/splashitem.cpp | 10 +- examples/graphicsview/padnavigator/splashitem.h | 2 + 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 +//! [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 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 #include +//! [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 > 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 +//! [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 #ifndef QT_NO_OPENGL #include #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() << 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(1.0)); - smoothScale->setKeyValueAt(0.5, qVariantValue(0.7)); - smoothScale->setKeyValueAt(1, qVariantValue(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(1.0)); + smoothFlipScale->setKeyValueAt(0.5, qVariantValue(0.7)); + smoothFlipScale->setKeyValueAt(1, qVariantValue(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(0.0)); frontState->assignProperty(backItem, "visible", false); + frontState->assignProperty(flipRotation, "angle", qVariantValue(0.0)); frontState->assignProperty(selectionItem, "visible", true); - frontState->assignProperty(pad, "fill", false); - backState->assignProperty(flipRotation, "angle", qVariantValue(180.0)); + backState->assignProperty(pad, "fill", true); + backState->assignProperty(backItem, "visible", true); backState->assignProperty(xRotation, "angle", qVariantValue(0.0)); backState->assignProperty(yRotation, "angle", qVariantValue(0.0)); + backState->assignProperty(flipRotation, "angle", qVariantValue(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 +#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 +//! [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 #include +//! [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 -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 +//! [0] class SplashItem : public QGraphicsObject { Q_OBJECT @@ -56,5 +57,6 @@ public: private: QString text; }; +//! [0] #endif // SPLASHITEM_H -- cgit v0.12