1
/****************************************************************************
3
** Copyright (C) 2016 The Qt Company Ltd.
4
** Contact: https://www.qt.io/licensing/
6
** This file is part of the documentation of the Qt Toolkit.
8
** $QT_BEGIN_LICENSE:FDL$
9
** Commercial License Usage
10
** Licensees holding valid commercial Qt licenses may use this file in
11
** accordance with the commercial license agreement provided with the
12
** Software or, alternatively, in accordance with the terms contained in
13
** a written agreement between you and The Qt Company. For licensing terms
14
** and conditions see https://www.qt.io/terms-conditions. For further
15
** information use the contact form at https://www.qt.io/contact-us.
17
** GNU Free Documentation License Usage
18
** Alternatively, this file may be used under the terms of the GNU Free
19
** Documentation License version 1.3 as published by the Free Software
20
** Foundation and appearing in the file included in the packaging of
21
** this file. Please review the following information to ensure
22
** the GNU Free Documentation License version 1.3 requirements
23
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
26
****************************************************************************/
29
\example desktop/screenshot
30
\title Screenshot Example
31
\ingroup examples-desktop
32
\brief The Screenshot example shows how to take a screenshot of the
35
\brief The Screenshot example shows how to take a screenshot of the
36
desktop using QScreen. It also shows how
37
to use QTimer to provide a single-shot timer, and how to
38
reimplement the QWidget::resizeEvent() event handler to make sure
39
that an application resizes smoothly and without data loss.
41
\image screenshot-example.png
43
With the application the users can take a screenshot of their
44
desktop. They are provided with a couple of options:
47
\li Delaying the screenshot, giving them time to rearrange
49
\li Hiding the application's window while the screenshot is taken.
52
In addition the application allows the users to save their
53
screenshot if they want to.
55
\section1 Screenshot Class Definition
57
\snippet desktop/screenshot/screenshot.h 0
59
The \c Screenshot class inherits QWidget and is the application's
60
main widget. It displays the application options and a preview of
63
We reimplement the QWidget::resizeEvent() function to make sure
64
that the preview of the screenshot scales properly when the user
65
resizes the application widget. We also need several private slots
66
to facilitate the options:
69
\li The \c newScreenshot() slot prepares a new screenshot.
70
\li The \c saveScreenshot() slot saves the last screenshot.
71
\li The \c shootScreen() slot takes the screenshot.
72
\li The \c updateCheckBox() slot enables or disables the
73
\uicontrol {Hide This Window} option.
76
We also declare the private function \c updateScreenshotLabel() which
77
is called whenever a new screenshot is taken or when a resize event
78
changes the size of the screenshot preview label.
80
In addition we need to store the screenshot's original pixmap. The
81
reason is that when we display the preview of the screenshot, we
82
need to scale its pixmap, storing the original we make sure that
83
no data are lost in that process.
85
\section1 Screenshot Class Implementation
87
\snippet desktop/screenshot/screenshot.cpp 0
89
In the constructor we first create the QLabel displaying the
92
We set the QLabel's size policy to be QSizePolicy::Expanding both
93
horizontally and vertically. This means that the QLabel's size
94
hint is a sensible size, but the widget can be shrunk and still be
95
useful. Also, the widget can make use of extra space, so it should
96
get as much space as possible. Then we make sure the QLabel is
97
aligned in the center of the \c Screenshot widget, and set its
100
Next, we create a group box that will contain all of the options'
101
widgets. Then we create a QSpinBox and a QLabel for the \uicontrol
102
{Screenshot Delay} option, and connect the spinbox to the \c
103
updateCheckBox() slot. Finally, we create a QCheckBox for the \uicontrol
104
{Hide This Window} option, add all the options' widgets to a
105
QGridLayout installed on the group box.
107
We create the applications's buttons and the group box containing
108
the application's options, and put it all into a main
109
layout. Finally we take the initial screenshot, and set the initial
110
delay and the window title, before we resize the widget to a
111
suitable size depending on the screen geometry.
113
\snippet desktop/screenshot/screenshot.cpp 1
115
The \c resizeEvent() function is reimplemented to receive the
116
resize events dispatched to the widget. The purpose is to scale
117
the preview screenshot pixmap without deformation of its content,
118
and also make sure that the application can be resized smoothly.
120
To achieve the first goal, we scale the screenshot pixmap using
121
Qt::KeepAspectRatio. We scale the pixmap to a rectangle as large
122
as possible inside the current size of the screenshot preview
123
label, preserving the aspect ratio. This means that if the user
124
resizes the application window in only one direction, the preview
125
screenshot keeps the same size.
127
To reach our second goal, we make sure that the preview screenshot
128
only is repainted (using the private \c updateScreenshotLabel()
129
function) when it actually changes its size.
131
\snippet desktop/screenshot/screenshot.cpp 2
133
The private \c newScreenshot() slot is called when the user
134
requests a new screenshot; but the slot only prepares a new
137
First we see if the \uicontrol {Hide This Window} option is checked, if
138
it is we hide the \c Screenshot widget. Then we disable the \uicontrol
139
{New Screenshot} button, to make sure the user only can request
140
one screenshot at a time.
142
We create a timer using the QTimer class which provides repetitive
143
and single-shot timers. We set the timer to time out only once,
144
using the static QTimer::singleShot() function. This function
145
calls the private \c shootScreen() slot after the time interval
146
specified by the \uicontrol {Screenshot Delay} option. It is \c
147
shootScreen() that actually performs the screenshot.
149
\snippet desktop/screenshot/screenshot.cpp 3
151
The \c saveScreenshot() slot is called when the user push the \uicontrol
152
Save button, and it presents a file dialog using the QFileDialog
155
QFileDialog enables a user to traverse the file system in order to
156
select one or many files or a directory. The easiest way to create
157
a QFileDialog is to use the convenience static
158
functions. Here, we instantiate the dialog on the stack in order
159
to be able to set up the supported mime types of QImageWriter,
160
allowing the user to save in a variety of formats.
162
We define the default file format to be png, and we make the file
163
dialog's initial path the location of pictures as obtained from
164
QStandardPaths, defaulting to the path the application is run from.
166
We run the dialog by invoking QDialog::exec() and return if the
167
user canceled the dialog. If the dialog has been accepted, we
168
obtain a file name by calling QFileDialog::selectedFiles().
169
The file does not have to exist. If the file
170
name is valid, we use the QPixmap::save() function to save the
171
screenshot's original pixmap in that file.
173
\snippet desktop/screenshot/screenshot.cpp 4
175
The \c shootScreen() slot is called to take the screenshot.
177
First, we find the instance of QScreen the window is located
178
by retrieving the QWindow and its QScreen, defaulting
179
to the primary screen. If no screen can be found, we return.
180
Although this is unlikely to happen, applications should check
181
for null pointers since there might be situations in which no
184
If the user has chosen to delay the screenshot, we make the application
185
beep when the screenshot is taken using the static
186
QApplication::beep() function.
188
We then take the screenshot using the QScreen::grabWindow()
189
function. The function grabs the contents of the window passed as
190
an argument, makes a pixmap out of it and returns that pixmap.
191
The window id can be obtained with QWidget::winId() or QWindow::winId().
192
Here, however, we just pass 0 as the window id, indicating that we
193
want to grab the entire screen.
195
We update the screenshot preview label using the private \c
196
updateScreenshotLabel() function. Then we enable the \uicontrol {New
197
Screenshot} button, and finally we make the \c Screenshot widget
198
visible if it was hidden during the screenshot.
200
\snippet desktop/screenshot/screenshot.cpp 6
202
The \uicontrol {Hide This Window} option is enabled or disabled
203
depending on the delay of the screenshot. If there is no delay,
204
the application window cannot be hidden and the option's checkbox
207
The \c updateCheckBox() slot is called whenever the user changes
208
the delay using the \uicontrol {Screenshot Delay} option.
210
\snippet desktop/screenshot/screenshot.cpp 10
212
The private \c updateScreenshotLabel() function is called whenever
213
the screenshot changes, or when a resize event changes the size of
214
the screenshot preview label. It updates the screenshot preview's
215
label using the QLabel::setPixmap() and QPixmap::scaled()
218
QPixmap::scaled() returns a copy of the given pixmap scaled to a
219
rectangle of the given size according to the given
220
Qt::AspectRatioMode and Qt::TransformationMode.
222
We scale the original pixmap to fit the current screenshot label's
223
size, preserving the aspect ratio and giving the resulting pixmap