|
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 desktop/screenshot |
|
44 \title Screenshot Example |
|
45 |
|
46 The Screenshot example shows how to take a screenshot of the |
|
47 desktop using QApplication and QDesktopWidget. It also shows how |
|
48 to use QTimer to provide a single-shot timer, and how to |
|
49 reimplement the QWidget::resizeEvent() event handler to make sure |
|
50 that an application resizes smoothly and without data loss. |
|
51 |
|
52 \image screenshot-example.png |
|
53 |
|
54 With the application the users can take a screenshot of their |
|
55 desktop. They are provided with a couple of options: |
|
56 |
|
57 \list |
|
58 \o Delaying the screenshot, giving them time to rearrange |
|
59 their desktop. |
|
60 \o Hiding the application's window while the screenshot is taken. |
|
61 \endlist |
|
62 |
|
63 In addition the application allows the users to save their |
|
64 screenshot if they want to. |
|
65 |
|
66 \section1 Screenshot Class Definition |
|
67 |
|
68 \snippet examples/desktop/screenshot/screenshot.h 0 |
|
69 |
|
70 The \c Screenshot class inherits QWidget and is the application's |
|
71 main widget. It displays the application options and a preview of |
|
72 the screenshot. |
|
73 |
|
74 We reimplement the QWidget::resizeEvent() function to make sure |
|
75 that the preview of the screenshot scales properly when the user |
|
76 resizes the application widget. We also need several private slots |
|
77 to facilitate the options: |
|
78 |
|
79 \list |
|
80 \o The \c newScreenshot() slot prepares a new screenshot. |
|
81 \o The \c saveScreenshot() slot saves the last screenshot. |
|
82 \o The \c shootScreen() slot takes the screenshot. |
|
83 \o The \c updateCheckBox() slot enables or disables the |
|
84 \gui {Hide This Window} option. |
|
85 \endlist |
|
86 |
|
87 We also declare some private functions: We use the \c |
|
88 createOptionsGroupBox(), \c createButtonsLayout() and \c |
|
89 createButton() functions when we construct the widget. And we call |
|
90 the private \c updateScreenshotLabel() function whenever a new |
|
91 screenshot is taken or when a resize event changes the size of the |
|
92 screenshot preview label. |
|
93 |
|
94 In addition we need to store the screenshot's original pixmap. The |
|
95 reason is that when we display the preview of the screenshot, we |
|
96 need to scale its pixmap, storing the original we make sure that |
|
97 no data are lost in that process. |
|
98 |
|
99 \section1 Screenshot Class Implementation |
|
100 |
|
101 \snippet examples/desktop/screenshot/screenshot.cpp 0 |
|
102 |
|
103 In the constructor we first create the QLabel displaying the |
|
104 screenshot preview. |
|
105 |
|
106 We set the QLabel's size policy to be QSizePolicy::Expanding both |
|
107 horizontally and vertically. This means that the QLabel's size |
|
108 hint is a sensible size, but the widget can be shrunk and still be |
|
109 useful. Also, the widget can make use of extra space, so it should |
|
110 get as much space as possible. Then we make sure the QLabel is |
|
111 aligned in the center of the \c Screenshot widget, and set its |
|
112 minimum size. |
|
113 |
|
114 We create the applications's buttons and the group box containing |
|
115 the application's options, and put it all into a main |
|
116 layout. Finally we take the initial screenshot, and set the inital |
|
117 delay and the window title, before we resize the widget to a |
|
118 suitable size. |
|
119 |
|
120 \snippet examples/desktop/screenshot/screenshot.cpp 1 |
|
121 |
|
122 The \c resizeEvent() function is reimplemented to receive the |
|
123 resize events dispatched to the widget. The purpose is to scale |
|
124 the preview screenshot pixmap without deformation of its content, |
|
125 and also make sure that the application can be resized smoothly. |
|
126 |
|
127 To achieve the first goal, we scale the screenshot pixmap using |
|
128 Qt::KeepAspectRatio. We scale the pixmap to a rectangle as large |
|
129 as possible inside the current size of the screenshot preview |
|
130 label, preserving the aspect ratio. This means that if the user |
|
131 resizes the application window in only one direction, the preview |
|
132 screenshot keeps the same size. |
|
133 |
|
134 To reach our second goal, we make sure that the preview screenshot |
|
135 only is repainted (using the private \c updateScreenshotLabel() |
|
136 function) when it actually changes its size. |
|
137 |
|
138 \snippet examples/desktop/screenshot/screenshot.cpp 2 |
|
139 |
|
140 The private \c newScreenshot() slot is called when the user |
|
141 requests a new screenshot; but the slot only prepares a new |
|
142 screenshot. |
|
143 |
|
144 First we see if the \gui {Hide This Window} option is checked, if |
|
145 it is we hide the \c Screenshot widget. Then we disable the \gui |
|
146 {New Screenshot} button, to make sure the user only can request |
|
147 one screenshot at a time. |
|
148 |
|
149 We create a timer using the QTimer class which provides repetitive |
|
150 and single-shot timers. We set the timer to time out only once, |
|
151 using the static QTimer::singleShot() function. This function |
|
152 calls the private \c shootScreen() slot after the time interval |
|
153 specified by the \gui {Screenshot Delay} option. It is \c |
|
154 shootScreen() that actually performs the screenshot. |
|
155 |
|
156 \snippet examples/desktop/screenshot/screenshot.cpp 3 |
|
157 |
|
158 The \c saveScreenshot() slot is called when the user push the \gui |
|
159 Save button, and it presents a file dialog using the QFileDialog |
|
160 class. |
|
161 |
|
162 QFileDialog enables a user to traverse the file system in order to |
|
163 select one or many files or a directory. The easiest way to create |
|
164 a QFileDialog is to use the convenience static |
|
165 functions. |
|
166 |
|
167 We define the default file format to be png, and we make the file |
|
168 dialog's initial path the path the application is run from. We |
|
169 create the file dialog using the static |
|
170 QFileDialog::getSaveFileName() function which returns a file name |
|
171 selected by the user. The file does not have to exist. If the file |
|
172 name is valid, we use the QPixmap::save() function to save the |
|
173 screenshot's original pixmap in that file. |
|
174 |
|
175 \snippet examples/desktop/screenshot/screenshot.cpp 4 |
|
176 |
|
177 The \c shootScreen() slot is called to take the screenshot. If the |
|
178 user has chosen to delay the screenshot, we make the application |
|
179 beep when the screenshot is taken using the static |
|
180 QApplication::beep() function. |
|
181 |
|
182 The QApplication class manages the GUI application's control flow |
|
183 and main settings. It contains the main event loop, where all |
|
184 events from the window system and other sources are processed and |
|
185 dispatched. |
|
186 |
|
187 \snippet examples/desktop/screenshot/screenshot.cpp 5 |
|
188 |
|
189 We take the screenshot using the static QPixmap::grabWindow() |
|
190 function. The function grabs the contents of the window passed as |
|
191 an argument, makes a pixmap out of it and returns that pixmap. |
|
192 |
|
193 We identify the argument window using the QWidget::winID() |
|
194 function which returns the window system identifier. Here it |
|
195 returns the identifier of the current QDesktopWidget retrieved by |
|
196 the QApplication::desktop() function. The QDesktopWidget class |
|
197 provides access to screen information, and inherits |
|
198 QWidget::winID(). |
|
199 |
|
200 We update the screenshot preview label using the private \c |
|
201 updateScreenshotLabel() function. Then we enable the \gui {New |
|
202 Screenshot} button, and finally we make the \c Screenshot widget |
|
203 visible if it was hidden during the screenshot. |
|
204 |
|
205 \snippet examples/desktop/screenshot/screenshot.cpp 6 |
|
206 |
|
207 The \gui {Hide This Window} option is enabled or disabled |
|
208 depending on the delay of the screenshot. If there is no delay, |
|
209 the application window cannot be hidden and the option's checkbox |
|
210 is disabled. |
|
211 |
|
212 The \c updateCheckBox() slot is called whenever the user changes |
|
213 the delay using the \gui {Screenshot Delay} option. |
|
214 |
|
215 \snippet examples/desktop/screenshot/screenshot.cpp 7 |
|
216 |
|
217 The private \c createOptionsGroupBox() function is called from the |
|
218 constructor. |
|
219 |
|
220 First we create a group box that will contain all of the options' |
|
221 widgets. Then we create a QSpinBox and a QLabel for the \gui |
|
222 {Screenshot Delay} option, and connect the spinbox to the \c |
|
223 updateCheckBox() slot. Finally, we create a QCheckBox for the \gui |
|
224 {Hide This Window} option, add all the options' widgets to a |
|
225 QGridLayout and install the layout on the group box. |
|
226 |
|
227 Note that we don't have to specify any parents for the widgets |
|
228 when we create them. The reason is that when we add a widget to a |
|
229 layout and install the layout on another widget, the layout's |
|
230 widgets are automatically reparented to the widget the layout is |
|
231 installed on. |
|
232 |
|
233 \snippet examples/desktop/screenshot/screenshot.cpp 8 |
|
234 |
|
235 The private \c createButtonsLayout() function is called from the |
|
236 constructor. We create the application's buttons using the private |
|
237 \c createButton() function, and add them to a QHBoxLayout. |
|
238 |
|
239 \snippet examples/desktop/screenshot/screenshot.cpp 9 |
|
240 |
|
241 The private \c createButton() function is called from the \c |
|
242 createButtonsLayout() function. It simply creates a QPushButton |
|
243 with the provided text, connects it to the provided receiver and |
|
244 slot, and returns a pointer to the button. |
|
245 |
|
246 \snippet examples/desktop/screenshot/screenshot.cpp 10 |
|
247 |
|
248 The private \c updateScreenshotLabel() function is called whenever |
|
249 the screenshot changes, or when a resize event changes the size of |
|
250 the screenshot preview label. It updates the screenshot preview's |
|
251 label using the QLabel::setPixmap() and QPixmap::scaled() |
|
252 functions. |
|
253 |
|
254 QPixmap::scaled() returns a copy of the given pixmap scaled to a |
|
255 rectangle of the given size according to the given |
|
256 Qt::AspectRatioMode and Qt::TransformationMode. |
|
257 |
|
258 We scale the original pixmap to fit the current screenshot label's |
|
259 size, preserving the aspect ratio and giving the resulting pixmap |
|
260 smoothed edges. |
|
261 */ |
|
262 |