|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the documentation of the Qt Toolkit. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
15 ** |
|
16 ** GNU Lesser General Public License Usage |
|
17 ** Alternatively, this file may be used under the terms of the GNU Lesser |
|
18 ** General Public License version 2.1 as published by the Free Software |
|
19 ** Foundation and appearing in the file LICENSE.LGPL included in the |
|
20 ** packaging of this file. Please review the following information to |
|
21 ** ensure the GNU Lesser General Public License version 2.1 requirements |
|
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
23 ** |
|
24 ** In addition, as a special exception, Nokia gives you certain additional |
|
25 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
27 ** |
|
28 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 /*! |
|
43 \example itemviews/pixelator |
|
44 \title Pixelator Example |
|
45 |
|
46 The Pixelator example shows how delegates can be used to customize the way that |
|
47 items are rendered in standard item views. |
|
48 |
|
49 \image pixelator-example.png |
|
50 |
|
51 By default, QTreeView, QTableView, and QListView use a standard item delegate |
|
52 to display and edit a set of common data types that are sufficient for many |
|
53 applications. However, an application may need to represent items of data in a |
|
54 particular way, or provide support for rendering more specialized data types, |
|
55 and this often requires the use of a custom delegate. |
|
56 |
|
57 In this example, we show how to use custom delegates to modify the appearance |
|
58 of standard views. To do this, we implement the following components: |
|
59 |
|
60 \list |
|
61 \i A model which represents each pixel in an image as an item of data, where each |
|
62 item contains a value for the brightness of the corresponding pixel. |
|
63 \i A custom delegate that uses the information supplied by the model to represent |
|
64 each pixel as a black circle on a white background, where the radius of the |
|
65 circle corresponds to the darkness of the pixel. |
|
66 \endlist |
|
67 |
|
68 This example may be useful for developers who want to implement their own table |
|
69 models or custom delegates. The process of creating custom delegates for editing |
|
70 item data is covered in the \l{Spin Box Delegate Example}{Spin Box Delegate} |
|
71 example. |
|
72 |
|
73 \section1 ImageModel Class Definition |
|
74 |
|
75 The \c ImageModel class is defined as follows: |
|
76 |
|
77 \snippet examples/itemviews/pixelator/imagemodel.h 0 |
|
78 |
|
79 Since we only require a simple, read-only table model, we only need to implement |
|
80 functions to indicate the dimensions of the image and supply data to other |
|
81 components. |
|
82 |
|
83 For convenience, the image to be used is passed in the constructor. |
|
84 |
|
85 \section1 ImageModel Class Implementation |
|
86 |
|
87 The constructor is trivial: |
|
88 |
|
89 \snippet examples/itemviews/pixelator/imagemodel.cpp 0 |
|
90 |
|
91 The \c setImage() function sets the image that will be used by the model: |
|
92 |
|
93 \snippet examples/itemviews/pixelator/imagemodel.cpp 1 |
|
94 |
|
95 The QAbstractItemModel::reset() call tells the view(s) that the model |
|
96 has changed. |
|
97 |
|
98 The \c rowCount() and \c columnCount() functions return the height and width of |
|
99 the image respectively: |
|
100 |
|
101 \snippet examples/itemviews/pixelator/imagemodel.cpp 2 |
|
102 \snippet examples/itemviews/pixelator/imagemodel.cpp 3 |
|
103 |
|
104 Since the image is a simple two-dimensional structure, the \c parent arguments |
|
105 to these functions are unused. They both simply return the relevant size from |
|
106 the underlying image object. |
|
107 |
|
108 The \c data() function returns data for the item that corresponds to a given |
|
109 model index in a format that is suitable for a particular role: |
|
110 |
|
111 \snippet examples/itemviews/pixelator/imagemodel.cpp 4 |
|
112 |
|
113 In this implementation, we only check that the model index is valid, and that |
|
114 the role requested is the \l{Qt::ItemDataRole}{DisplayRole}. If so, the function |
|
115 returns the grayscale value of the relevant pixel in the image; otherwise, a null |
|
116 model index is returned. |
|
117 |
|
118 This model can be used with QTableView to display the integer brightness values |
|
119 for the pixels in the image. However, we will implement a custom delegate to |
|
120 display this information in a more artistic way. |
|
121 |
|
122 The \c headerData() function is also reimplemented: |
|
123 |
|
124 \snippet examples/itemviews/pixelator/imagemodel.cpp 5 |
|
125 |
|
126 We return (1, 1) as the size hint for a header item. If we |
|
127 didn't, the headers would default to a larger size, preventing |
|
128 us from displaying really small items (which can be specified |
|
129 using the \gui{Pixel size} combobox). |
|
130 |
|
131 \section1 PixelDelegate Class Definition |
|
132 |
|
133 The \c PixelDelegate class is defined as follows: |
|
134 |
|
135 \snippet examples/itemviews/pixelator/pixeldelegate.h 0 |
|
136 |
|
137 This class provides only basic features for a delegate so, unlike the |
|
138 \l{Spin Box Delegate Example}{Spin Box Delegate} example, we subclass |
|
139 QAbstractItemDelegate instead of QItemDelegate. |
|
140 |
|
141 We only need to reimplement \l{QAbstractItemDelegate::paint()}{paint()} and |
|
142 \l{QAbstractItemDelegate::sizeHint()}{sizeHint()} in this class. |
|
143 However, we also provide a delegate-specific \c setPixelSize() function so |
|
144 that we can change the delegate's behavior via the signals and slots mechanism. |
|
145 |
|
146 \section1 PixelDelegate Class Implementation |
|
147 |
|
148 The \c PixelDelegate constructor is used to set up a default value for |
|
149 the size of each "pixel" that it renders. The base class constructor is |
|
150 also called to ensure that the delegate is set up with a parent object, |
|
151 if one is supplied: |
|
152 |
|
153 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 0 |
|
154 |
|
155 Each item is rendered by the delegate's |
|
156 \l{QAbstractItemDelegate::paint()}{paint()} function. The view calls this |
|
157 function with a ready-to-use QPainter object, style information that the |
|
158 delegate should use to correctly draw the item, and an index to the item in |
|
159 the model: |
|
160 |
|
161 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 1 |
|
162 |
|
163 The first task the delegate has to perform is to draw the item's background |
|
164 correctly. Usually, selected items appear differently to non-selected items, |
|
165 so we begin by testing the state passed in the style option and filling the |
|
166 background if necessary. |
|
167 |
|
168 The radius of each circle is calculated in the following lines of code: |
|
169 |
|
170 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 3 |
|
171 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 4 |
|
172 |
|
173 First, the largest possible radius of the circle is determined by taking the |
|
174 smallest dimension of the style option's \c rect attribute. |
|
175 Using the model index supplied, we obtain a value for the brightness of the |
|
176 relevant pixel in the image. The radius of the circle is calculated by |
|
177 scaling the brightness to fit within the item and subtracting it from the |
|
178 largest possible radius. |
|
179 |
|
180 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 5 |
|
181 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 6 |
|
182 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 7 |
|
183 |
|
184 We save the painter's state, turn on antialiasing (to obtain smoother |
|
185 curves), and turn off the pen. |
|
186 |
|
187 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 8 |
|
188 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 9 |
|
189 |
|
190 The foreground of the item (the circle representing a pixel) must be |
|
191 rendered using an appropriate brush. For unselected items, we will use a |
|
192 solid black brush; selected items are drawn using a predefined brush from |
|
193 the style option's palette. |
|
194 |
|
195 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 10 |
|
196 |
|
197 Finally, we paint the circle within the rectangle specified by the style |
|
198 option and we call \l{QPainter::}{restore()} on the painter. |
|
199 |
|
200 The \c paint() function does not have to be particularly complicated; it is |
|
201 only necessary to ensure that the state of the painter when the function |
|
202 returns is the same as it was when it was called. This usually |
|
203 means that any transformations applied to the painter must be preceded by |
|
204 a call to QPainter::save() and followed by a call to QPainter::restore(). |
|
205 |
|
206 The delegate's \l{QAbstractItemDelegate::}{sizeHint()} function |
|
207 returns a size for the item based on the predefined pixel size, initially set |
|
208 up in the constructor: |
|
209 |
|
210 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 11 |
|
211 |
|
212 The delegate's size is updated whenever the pixel size is changed. |
|
213 We provide a custom slot to do this: |
|
214 |
|
215 \snippet examples/itemviews/pixelator/pixeldelegate.cpp 12 |
|
216 |
|
217 \section1 Using The Custom Delegate |
|
218 |
|
219 In this example, we use a main window to display a table of data, using the |
|
220 custom delegate to render each cell in a particular way. Much of the |
|
221 \c MainWindow class performs tasks that are not related to item views. Here, |
|
222 we only quote the parts that are relevant. You can look at the rest of the |
|
223 implementation by following the links to the code at the top of this |
|
224 document. |
|
225 |
|
226 In the constructor, we set up a table view, turn off its grid, and hide its |
|
227 headers: |
|
228 |
|
229 \snippet examples/itemviews/pixelator/mainwindow.cpp 0 |
|
230 \dots |
|
231 \snippet examples/itemviews/pixelator/mainwindow.cpp 1 |
|
232 |
|
233 This enables the items to be drawn without any gaps between them. Removing |
|
234 the headers also prevents the user from adjusting the sizes of individual |
|
235 rows and columns. |
|
236 |
|
237 We also set the minimum section size to 1 on the headers. If we |
|
238 didn't, the headers would default to a larger size, preventing |
|
239 us from displaying really small items (which can be specified |
|
240 using the \gui{Pixel size} combobox). |
|
241 |
|
242 The custom delegate is constructed with the main window as its parent, so |
|
243 that it will be deleted correctly later, and we set it on the table view. |
|
244 |
|
245 \snippet examples/itemviews/pixelator/mainwindow.cpp 2 |
|
246 |
|
247 Each item in the table view will be rendered by the \c PixelDelegate |
|
248 instance. |
|
249 |
|
250 We construct a spin box to allow the user to change the size of each "pixel" |
|
251 drawn by the delegate: |
|
252 |
|
253 \snippet examples/itemviews/pixelator/mainwindow.cpp 3 |
|
254 |
|
255 This spin box is connected to the custom slot we implemented in the |
|
256 \c PixelDelegate class. This ensures that the delegate always draws each |
|
257 pixel at the currently specified size: |
|
258 |
|
259 \snippet examples/itemviews/pixelator/mainwindow.cpp 4 |
|
260 \dots |
|
261 \snippet examples/itemviews/pixelator/mainwindow.cpp 5 |
|
262 |
|
263 We also connect the spin box to a slot in the \c MainWindow class. This |
|
264 forces the view to take into account the new size hints for each item; |
|
265 these are provided by the delegate in its \c sizeHint() function. |
|
266 |
|
267 \snippet examples/itemviews/pixelator/mainwindow.cpp 6 |
|
268 |
|
269 We explicitly resize the columns and rows to match the |
|
270 \gui{Pixel size} combobox. |
|
271 */ |