diff options
Diffstat (limited to 'doc/src/examples/pixelator.qdoc')
-rw-r--r-- | doc/src/examples/pixelator.qdoc | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/doc/src/examples/pixelator.qdoc b/doc/src/examples/pixelator.qdoc new file mode 100644 index 0000000..2a8b43d --- /dev/null +++ b/doc/src/examples/pixelator.qdoc @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the documentation of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain +** additional rights. These rights are described in the Nokia Qt LGPL +** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/*! + \example itemviews/pixelator + \title Pixelator Example + + The Pixelator example shows how delegates can be used to customize the way that + items are rendered in standard item views. + + \image pixelator-example.png + + By default, QTreeView, QTableView, and QListView use a standard item delegate + to display and edit a set of common data types that are sufficient for many + applications. However, an application may need to represent items of data in a + particular way, or provide support for rendering more specialized data types, + and this often requires the use of a custom delegate. + + In this example, we show how to use custom delegates to modify the appearance + of standard views. To do this, we implement the following components: + + \list + \i A model which represents each pixel in an image as an item of data, where each + item contains a value for the brightness of the corresponding pixel. + \i A custom delegate that uses the information supplied by the model to represent + each pixel as a black circle on a white background, where the radius of the + circle corresponds to the darkness of the pixel. + \endlist + + This example may be useful for developers who want to implement their own table + models or custom delegates. The process of creating custom delegates for editing + item data is covered in the \l{Spin Box Delegate Example}{Spin Box Delegate} + example. + + \section1 ImageModel Class Definition + + The \c ImageModel class is defined as follows: + + \snippet examples/itemviews/pixelator/imagemodel.h 0 + + Since we only require a simple, read-only table model, we only need to implement + functions to indicate the dimensions of the image and supply data to other + components. + + For convenience, the image to be used is passed in the constructor. + + \section1 ImageModel Class Implementation + + The constructor is trivial: + + \snippet examples/itemviews/pixelator/imagemodel.cpp 0 + + The \c setImage() function sets the image that will be used by the model: + + \snippet examples/itemviews/pixelator/imagemodel.cpp 1 + + The QAbstractItemModel::reset() call tells the view(s) that the model + has changed. + + The \c rowCount() and \c columnCount() functions return the height and width of + the image respectively: + + \snippet examples/itemviews/pixelator/imagemodel.cpp 2 + \snippet examples/itemviews/pixelator/imagemodel.cpp 3 + + Since the image is a simple two-dimensional structure, the \c parent arguments + to these functions are unused. They both simply return the relevant size from + the underlying image object. + + The \c data() function returns data for the item that corresponds to a given + model index in a format that is suitable for a particular role: + + \snippet examples/itemviews/pixelator/imagemodel.cpp 4 + + In this implementation, we only check that the model index is valid, and that + the role requested is the \l{Qt::ItemDataRole}{DisplayRole}. If so, the function + returns the grayscale value of the relevant pixel in the image; otherwise, a null + model index is returned. + + This model can be used with QTableView to display the integer brightness values + for the pixels in the image. However, we will implement a custom delegate to + display this information in a more artistic way. + + The \c headerData() function is also reimplemented: + + \snippet examples/itemviews/pixelator/imagemodel.cpp 5 + + We return (1, 1) as the size hint for a header item. If we + didn't, the headers would default to a larger size, preventing + us from displaying really small items (which can be specified + using the \gui{Pixel size} combobox). + + \section1 PixelDelegate Class Definition + + The \c PixelDelegate class is defined as follows: + + \snippet examples/itemviews/pixelator/pixeldelegate.h 0 + + This class provides only basic features for a delegate so, unlike the + \l{Spin Box Delegate Example}{Spin Box Delegate} example, we subclass + QAbstractItemDelegate instead of QItemDelegate. + + We only need to reimplement \l{QAbstractItemDelegate::paint()}{paint()} and + \l{QAbstractItemDelegate::sizeHint()}{sizeHint()} in this class. + However, we also provide a delegate-specific \c setPixelSize() function so + that we can change the delegate's behavior via the signals and slots mechanism. + + \section1 PixelDelegate Class Implementation + + The \c PixelDelegate constructor is used to set up a default value for + the size of each "pixel" that it renders. The base class constructor is + also called to ensure that the delegate is set up with a parent object, + if one is supplied: + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 0 + + Each item is rendered by the delegate's + \l{QAbstractItemDelegate::paint()}{paint()} function. The view calls this + function with a ready-to-use QPainter object, style information that the + delegate should use to correctly draw the item, and an index to the item in + the model: + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 1 + + The first task the delegate has to perform is to draw the item's background + correctly. Usually, selected items appear differently to non-selected items, + so we begin by testing the state passed in the style option and filling the + background if necessary. + + The radius of each circle is calculated in the following lines of code: + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 3 + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 4 + + First, the largest possible radius of the circle is determined by taking the + smallest dimension of the style option's \c rect attribute. + Using the model index supplied, we obtain a value for the brightness of the + relevant pixel in the image. The radius of the circle is calculated by + scaling the brightness to fit within the item and subtracting it from the + largest possible radius. + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 5 + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 6 + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 7 + + We save the painter's state, turn on antialiasing (to obtain smoother + curves), and turn off the pen. + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 8 + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 9 + + The foreground of the item (the circle representing a pixel) must be + rendered using an appropriate brush. For unselected items, we will use a + solid black brush; selected items are drawn using a predefined brush from + the style option's palette. + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 10 + + Finally, we paint the circle within the rectangle specified by the style + option and we call \l{QPainter::}{restore()} on the painter. + + The \c paint() function does not have to be particularly complicated; it is + only necessary to ensure that the state of the painter when the function + returns is the same as it was when it was called. This usually + means that any transformations applied to the painter must be preceded by + a call to QPainter::save() and followed by a call to QPainter::restore(). + + The delegate's \l{QAbstractItemDelegate::}{sizeHint()} function + returns a size for the item based on the predefined pixel size, initially set + up in the constructor: + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 11 + + The delegate's size is updated whenever the pixel size is changed. + We provide a custom slot to do this: + + \snippet examples/itemviews/pixelator/pixeldelegate.cpp 12 + + \section1 Using The Custom Delegate + + In this example, we use a main window to display a table of data, using the + custom delegate to render each cell in a particular way. Much of the + \c MainWindow class performs tasks that are not related to item views. Here, + we only quote the parts that are relevant. You can look at the rest of the + implementation by following the links to the code at the top of this + document. + + In the constructor, we set up a table view, turn off its grid, and hide its + headers: + + \snippet examples/itemviews/pixelator/mainwindow.cpp 0 + \dots + \snippet examples/itemviews/pixelator/mainwindow.cpp 1 + + This enables the items to be drawn without any gaps between them. Removing + the headers also prevents the user from adjusting the sizes of individual + rows and columns. + + We also set the minimum section size to 1 on the headers. If we + didn't, the headers would default to a larger size, preventing + us from displaying really small items (which can be specified + using the \gui{Pixel size} combobox). + + The custom delegate is constructed with the main window as its parent, so + that it will be deleted correctly later, and we set it on the table view. + + \snippet examples/itemviews/pixelator/mainwindow.cpp 2 + + Each item in the table view will be rendered by the \c PixelDelegate + instance. + + We construct a spin box to allow the user to change the size of each "pixel" + drawn by the delegate: + + \snippet examples/itemviews/pixelator/mainwindow.cpp 3 + + This spin box is connected to the custom slot we implemented in the + \c PixelDelegate class. This ensures that the delegate always draws each + pixel at the currently specified size: + + \snippet examples/itemviews/pixelator/mainwindow.cpp 4 + \dots + \snippet examples/itemviews/pixelator/mainwindow.cpp 5 + + We also connect the spin box to a slot in the \c MainWindow class. This + forces the view to take into account the new size hints for each item; + these are provided by the delegate in its \c sizeHint() function. + + \snippet examples/itemviews/pixelator/mainwindow.cpp 6 + + We explicitly resize the columns and rows to match the + \gui{Pixel size} combobox. +*/ |