2011-04-27 10:05:43 +00:00
|
|
|
/****************************************************************************
|
|
|
|
**
|
2012-01-05 04:03:39 +00:00
|
|
|
** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
|
2012-01-20 03:06:31 +00:00
|
|
|
** Contact: http://www.qt-project.org/
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
|
|
|
** This file is part of the documentation of the Qt Toolkit.
|
|
|
|
**
|
|
|
|
** $QT_BEGIN_LICENSE:FDL$
|
|
|
|
** GNU Free Documentation License
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU Free
|
|
|
|
** Documentation License version 1.3 as published by the Free Software
|
2011-05-24 09:34:08 +00:00
|
|
|
** Foundation and appearing in the file included in the packaging of
|
|
|
|
** this file.
|
|
|
|
**
|
|
|
|
** Other Usage
|
|
|
|
** Alternatively, this file may be used in accordance with the terms
|
|
|
|
** and conditions contained in a signed written agreement between you
|
|
|
|
** and Nokia.
|
|
|
|
**
|
|
|
|
**
|
|
|
|
**
|
2011-04-27 10:05:43 +00:00
|
|
|
**
|
2012-01-24 06:17:24 +00:00
|
|
|
**
|
2011-04-27 10:05:43 +00:00
|
|
|
** $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.
|
|
|
|
|
|
|
|
\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.
|
|
|
|
*/
|