| /**************************************************************************** |
| ** |
| ** Copyright (C) 2016 The Qt Company Ltd. |
| ** Contact: https://www.qt.io/licensing/ |
| ** |
| ** This file is part of the documentation of the Qt Toolkit. |
| ** |
| ** $QT_BEGIN_LICENSE:FDL$ |
| ** Commercial License Usage |
| ** Licensees holding valid commercial Qt licenses may use this file in |
| ** accordance with the commercial license agreement provided with the |
| ** Software or, alternatively, in accordance with the terms contained in |
| ** a written agreement between you and The Qt Company. For licensing terms |
| ** and conditions see https://www.qt.io/terms-conditions. For further |
| ** information use the contact form at https://www.qt.io/contact-us. |
| ** |
| ** GNU Free Documentation License Usage |
| ** Alternatively, this file may be used under the terms of the GNU Free |
| ** Documentation License version 1.3 as published by the Free Software |
| ** Foundation and appearing in the file included in the packaging of |
| ** this file. Please review the following information to ensure |
| ** the GNU Free Documentation License version 1.3 requirements |
| ** will be met: https://www.gnu.org/licenses/fdl-1.3.html. |
| ** $QT_END_LICENSE$ |
| ** |
| ****************************************************************************/ |
| |
| /*! |
| \example desktop/screenshot |
| \title Screenshot Example |
| \ingroup examples-desktop |
| \brief The Screenshot example shows how to take a screenshot of the |
| desktop. |
| |
| \brief The Screenshot example shows how to take a screenshot of the |
| desktop using QScreen. It also shows how |
| to use QTimer to provide a single-shot timer, and how to |
| reimplement the QWidget::resizeEvent() event handler to make sure |
| that an application resizes smoothly and without data loss. |
| |
| \image screenshot-example.png |
| |
| With the application the users can take a screenshot of their |
| desktop. They are provided with a couple of options: |
| |
| \list |
| \li Delaying the screenshot, giving them time to rearrange |
| their desktop. |
| \li Hiding the application's window while the screenshot is taken. |
| \endlist |
| |
| In addition the application allows the users to save their |
| screenshot if they want to. |
| |
| \section1 Screenshot Class Definition |
| |
| \snippet desktop/screenshot/screenshot.h 0 |
| |
| The \c Screenshot class inherits QWidget and is the application's |
| main widget. It displays the application options and a preview of |
| the screenshot. |
| |
| We reimplement the QWidget::resizeEvent() function to make sure |
| that the preview of the screenshot scales properly when the user |
| resizes the application widget. We also need several private slots |
| to facilitate the options: |
| |
| \list |
| \li The \c newScreenshot() slot prepares a new screenshot. |
| \li The \c saveScreenshot() slot saves the last screenshot. |
| \li The \c shootScreen() slot takes the screenshot. |
| \li The \c updateCheckBox() slot enables or disables the |
| \uicontrol {Hide This Window} option. |
| \endlist |
| |
| We also declare the private function \c updateScreenshotLabel() which |
| is called whenever a new screenshot is taken or when a resize event |
| changes the size of the screenshot preview label. |
| |
| In addition we need to store the screenshot's original pixmap. The |
| reason is that when we display the preview of the screenshot, we |
| need to scale its pixmap, storing the original we make sure that |
| no data are lost in that process. |
| |
| \section1 Screenshot Class Implementation |
| |
| \snippet desktop/screenshot/screenshot.cpp 0 |
| |
| In the constructor we first create the QLabel displaying the |
| screenshot preview. |
| |
| We set the QLabel's size policy to be QSizePolicy::Expanding both |
| horizontally and vertically. This means that the QLabel's size |
| hint is a sensible size, but the widget can be shrunk and still be |
| useful. Also, the widget can make use of extra space, so it should |
| get as much space as possible. Then we make sure the QLabel is |
| aligned in the center of the \c Screenshot widget, and set its |
| minimum size. |
| |
| Next, we create a group box that will contain all of the options' |
| widgets. Then we create a QSpinBox and a QLabel for the \uicontrol |
| {Screenshot Delay} option, and connect the spinbox to the \c |
| updateCheckBox() slot. Finally, we create a QCheckBox for the \uicontrol |
| {Hide This Window} option, add all the options' widgets to a |
| QGridLayout installed on the group box. |
| |
| We create the applications's buttons and the group box containing |
| the application's options, and put it all into a main |
| layout. Finally we take the initial screenshot, and set the initial |
| delay and the window title, before we resize the widget to a |
| suitable size depending on the screen geometry. |
| |
| \snippet desktop/screenshot/screenshot.cpp 1 |
| |
| The \c resizeEvent() function is reimplemented to receive the |
| resize events dispatched to the widget. The purpose is to scale |
| the preview screenshot pixmap without deformation of its content, |
| and also make sure that the application can be resized smoothly. |
| |
| To achieve the first goal, we scale the screenshot pixmap using |
| Qt::KeepAspectRatio. We scale the pixmap to a rectangle as large |
| as possible inside the current size of the screenshot preview |
| label, preserving the aspect ratio. This means that if the user |
| resizes the application window in only one direction, the preview |
| screenshot keeps the same size. |
| |
| To reach our second goal, we make sure that the preview screenshot |
| only is repainted (using the private \c updateScreenshotLabel() |
| function) when it actually changes its size. |
| |
| \snippet desktop/screenshot/screenshot.cpp 2 |
| |
| The private \c newScreenshot() slot is called when the user |
| requests a new screenshot; but the slot only prepares a new |
| screenshot. |
| |
| First we see if the \uicontrol {Hide This Window} option is checked, if |
| it is we hide the \c Screenshot widget. Then we disable the \uicontrol |
| {New Screenshot} button, to make sure the user only can request |
| one screenshot at a time. |
| |
| We create a timer using the QTimer class which provides repetitive |
| and single-shot timers. We set the timer to time out only once, |
| using the static QTimer::singleShot() function. This function |
| calls the private \c shootScreen() slot after the time interval |
| specified by the \uicontrol {Screenshot Delay} option. It is \c |
| shootScreen() that actually performs the screenshot. |
| |
| \snippet desktop/screenshot/screenshot.cpp 3 |
| |
| The \c saveScreenshot() slot is called when the user push the \uicontrol |
| Save button, and it presents a file dialog using the QFileDialog |
| class. |
| |
| QFileDialog enables a user to traverse the file system in order to |
| select one or many files or a directory. The easiest way to create |
| a QFileDialog is to use the convenience static |
| functions. Here, we instantiate the dialog on the stack in order |
| to be able to set up the supported mime types of QImageWriter, |
| allowing the user to save in a variety of formats. |
| |
| We define the default file format to be png, and we make the file |
| dialog's initial path the location of pictures as obtained from |
| QStandardPaths, defaulting to the path the application is run from. |
| |
| We run the dialog by invoking QDialog::exec() and return if the |
| user canceled the dialog. If the dialog has been accepted, we |
| obtain a file name by calling QFileDialog::selectedFiles(). |
| The file does not have to exist. If the file |
| name is valid, we use the QPixmap::save() function to save the |
| screenshot's original pixmap in that file. |
| |
| \snippet desktop/screenshot/screenshot.cpp 4 |
| |
| The \c shootScreen() slot is called to take the screenshot. |
| |
| First, we find the instance of QScreen the window is located |
| by retrieving the QWindow and its QScreen, defaulting |
| to the primary screen. If no screen can be found, we return. |
| Although this is unlikely to happen, applications should check |
| for null pointers since there might be situations in which no |
| screen is connected. |
| |
| If the user has chosen to delay the screenshot, we make the application |
| beep when the screenshot is taken using the static |
| QApplication::beep() function. |
| |
| We then take the screenshot using the QScreen::grabWindow() |
| function. The function grabs the contents of the window passed as |
| an argument, makes a pixmap out of it and returns that pixmap. |
| The window id can be obtained with QWidget::winId() or QWindow::winId(). |
| Here, however, we just pass 0 as the window id, indicating that we |
| want to grab the entire screen. |
| |
| We update the screenshot preview label using the private \c |
| updateScreenshotLabel() function. Then we enable the \uicontrol {New |
| Screenshot} button, and finally we make the \c Screenshot widget |
| visible if it was hidden during the screenshot. |
| |
| \snippet desktop/screenshot/screenshot.cpp 6 |
| |
| The \uicontrol {Hide This Window} option is enabled or disabled |
| depending on the delay of the screenshot. If there is no delay, |
| the application window cannot be hidden and the option's checkbox |
| is disabled. |
| |
| The \c updateCheckBox() slot is called whenever the user changes |
| the delay using the \uicontrol {Screenshot Delay} option. |
| |
| \snippet desktop/screenshot/screenshot.cpp 10 |
| |
| The private \c updateScreenshotLabel() function is called whenever |
| the screenshot changes, or when a resize event changes the size of |
| the screenshot preview label. It updates the screenshot preview's |
| label using the QLabel::setPixmap() and QPixmap::scaled() |
| functions. |
| |
| QPixmap::scaled() returns a copy of the given pixmap scaled to a |
| rectangle of the given size according to the given |
| Qt::AspectRatioMode and Qt::TransformationMode. |
| |
| We scale the original pixmap to fit the current screenshot label's |
| size, preserving the aspect ratio and giving the resulting pixmap |
| smoothed edges. |
| */ |
| |