diff --git a/examples/widgets/desktop/screenshot/main.cpp b/examples/widgets/desktop/screenshot/main.cpp index 788ebb353297d040cfcac4bcddd71fe9f9854baf..811562858a11902367e506fd8c535b405abcbda5 100644 --- a/examples/widgets/desktop/screenshot/main.cpp +++ b/examples/widgets/desktop/screenshot/main.cpp @@ -39,13 +39,16 @@ ****************************************************************************/ #include <QApplication> +#include <QDesktopWidget> #include "screenshot.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); + Screenshot screenshot; + screenshot.move(QApplication::desktop()->availableGeometry(&screenshot).topLeft() + QPoint(20, 20)); screenshot.show(); return app.exec(); } diff --git a/examples/widgets/desktop/screenshot/screenshot.cpp b/examples/widgets/desktop/screenshot/screenshot.cpp index bfca5a45ae75476c6a875bf03b11036118d141b8..354fe36369d3fb80bf1c3f69457e269c0d9399eb 100644 --- a/examples/widgets/desktop/screenshot/screenshot.cpp +++ b/examples/widgets/desktop/screenshot/screenshot.cpp @@ -44,20 +44,48 @@ //! [0] Screenshot::Screenshot() + : screenshotLabel(new QLabel(this)) { - screenshotLabel = new QLabel; screenshotLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); screenshotLabel->setAlignment(Qt::AlignCenter); - screenshotLabel->setMinimumSize(240, 160); - createOptionsGroupBox(); - createButtonsLayout(); + const QRect screenGeometry = QApplication::desktop()->screenGeometry(this); + screenshotLabel->setMinimumSize(screenGeometry.width() / 8, screenGeometry.height() / 8); - mainLayout = new QVBoxLayout; + QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(screenshotLabel); + + QGroupBox *optionsGroupBox = new QGroupBox(tr("Options"), this); + delaySpinBox = new QSpinBox(optionsGroupBox); + delaySpinBox->setSuffix(tr(" s")); + delaySpinBox->setMaximum(60); + + typedef void (QSpinBox::*QSpinBoxIntSignal)(int); + connect(delaySpinBox, static_cast<QSpinBoxIntSignal>(&QSpinBox::valueChanged), + this, &Screenshot::updateCheckBox); + + hideThisWindowCheckBox = new QCheckBox(tr("Hide This Window"), optionsGroupBox); + + QGridLayout *optionsGroupBoxLayout = new QGridLayout(optionsGroupBox); + optionsGroupBoxLayout->addWidget(new QLabel(tr("Screenshot Delay:"), this), 0, 0); + optionsGroupBoxLayout->addWidget(delaySpinBox, 0, 1); + optionsGroupBoxLayout->addWidget(hideThisWindowCheckBox, 1, 0, 1, 2); + mainLayout->addWidget(optionsGroupBox); + + QHBoxLayout *buttonsLayout = new QHBoxLayout; + newScreenshotButton = new QPushButton(tr("New Screenshot"), this); + connect(newScreenshotButton, &QPushButton::clicked, this, &Screenshot::newScreenshot); + buttonsLayout->addWidget(newScreenshotButton); + QPushButton *saveScreenshotButton = new QPushButton(tr("Save Screenshot"), this); + connect(saveScreenshotButton, &QPushButton::clicked, this, &Screenshot::saveScreenshot); + buttonsLayout->addWidget(saveScreenshotButton); + QPushButton *quitScreenshotButton = new QPushButton(tr("Quit"), this); + quitScreenshotButton->setShortcut(Qt::CTRL + Qt::Key_Q); + connect(quitScreenshotButton, &QPushButton::clicked, this, &QWidget::close); + buttonsLayout->addWidget(quitScreenshotButton); + buttonsLayout->addStretch(); mainLayout->addLayout(buttonsLayout); - setLayout(mainLayout); shootScreen(); delaySpinBox->setValue(5); @@ -84,44 +112,59 @@ void Screenshot::newScreenshot() hide(); newScreenshotButton->setDisabled(true); - QTimer::singleShot(delaySpinBox->value() * 1000, this, SLOT(shootScreen())); + QTimer::singleShot(delaySpinBox->value() * 1000, this, &Screenshot::shootScreen); } //! [2] //! [3] void Screenshot::saveScreenshot() { - QString format = "png"; - QString initialPath = QDir::currentPath() + tr("/untitled.") + format; - - QString fileName = QFileDialog::getSaveFileName(this, tr("Save As"), initialPath, - tr("%1 Files (*.%2);;All Files (*)") - .arg(format.toUpper()) - .arg(format)); - if (!fileName.isEmpty()) - originalPixmap.save(fileName, format.toLatin1().constData()); + const QString format = "png"; + QString initialPath = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); + if (initialPath.isEmpty()) + initialPath = QDir::currentPath(); + initialPath += tr("/untitled.") + format; + + QFileDialog fileDialog(this, tr("Save As"), initialPath); + fileDialog.setAcceptMode(QFileDialog::AcceptSave); + fileDialog.setFileMode(QFileDialog::AnyFile); + fileDialog.setDirectory(initialPath); + QStringList mimeTypes; + foreach (const QByteArray &bf, QImageWriter::supportedMimeTypes()) + mimeTypes.append(QLatin1String(bf)); + fileDialog.setMimeTypeFilters(mimeTypes); + fileDialog.selectMimeTypeFilter("image/" + format); + fileDialog.setDefaultSuffix(format); + if (fileDialog.exec() != QDialog::Accepted) + return; + const QString fileName = fileDialog.selectedFiles().first(); + if (!originalPixmap.save(fileName)) { + QMessageBox::warning(this, tr("Save Error"), tr("The image could not be saved to \"%1\".") + .arg(QDir::toNativeSeparators(fileName))); + } } //! [3] //! [4] void Screenshot::shootScreen() { - if (delaySpinBox->value() != 0) - qApp->beep(); -//! [4] - originalPixmap = QPixmap(); // clear image for low memory situations - // on embedded devices. -//! [5] QScreen *screen = QGuiApplication::primaryScreen(); - if (screen) - originalPixmap = screen->grabWindow(0); + if (const QWindow *window = windowHandle()) + screen = window->screen(); + if (!screen) + return; + + if (delaySpinBox->value() != 0) + QApplication::beep(); + + originalPixmap = screen->grabWindow(0); updateScreenshotLabel(); newScreenshotButton->setDisabled(false); if (hideThisWindowCheckBox->isChecked()) show(); } -//! [5] +//! [4] //! [6] void Screenshot::updateCheckBox() @@ -135,52 +178,6 @@ void Screenshot::updateCheckBox() } //! [6] -//! [7] -void Screenshot::createOptionsGroupBox() -{ - optionsGroupBox = new QGroupBox(tr("Options")); - - delaySpinBox = new QSpinBox; - delaySpinBox->setSuffix(tr(" s")); - delaySpinBox->setMaximum(60); - connect(delaySpinBox, SIGNAL(valueChanged(int)), this, SLOT(updateCheckBox())); - - delaySpinBoxLabel = new QLabel(tr("Screenshot Delay:")); - - hideThisWindowCheckBox = new QCheckBox(tr("Hide This Window")); - - optionsGroupBoxLayout = new QGridLayout; - optionsGroupBoxLayout->addWidget(delaySpinBoxLabel, 0, 0); - optionsGroupBoxLayout->addWidget(delaySpinBox, 0, 1); - optionsGroupBoxLayout->addWidget(hideThisWindowCheckBox, 1, 0, 1, 2); - optionsGroupBox->setLayout(optionsGroupBoxLayout); -} -//! [7] - -//! [8] -void Screenshot::createButtonsLayout() -{ - newScreenshotButton = createButton(tr("New Screenshot"), this, SLOT(newScreenshot())); - saveScreenshotButton = createButton(tr("Save Screenshot"), this, SLOT(saveScreenshot())); - quitScreenshotButton = createButton(tr("Quit"), this, SLOT(close())); - - buttonsLayout = new QHBoxLayout; - buttonsLayout->addStretch(); - buttonsLayout->addWidget(newScreenshotButton); - buttonsLayout->addWidget(saveScreenshotButton); - buttonsLayout->addWidget(quitScreenshotButton); -} -//! [8] - -//! [9] -QPushButton *Screenshot::createButton(const QString &text, QWidget *receiver, - const char *member) -{ - QPushButton *button = new QPushButton(text); - button->connect(button, SIGNAL(clicked()), receiver, member); - return button; -} -//! [9] //! [10] void Screenshot::updateScreenshotLabel() diff --git a/examples/widgets/desktop/screenshot/screenshot.h b/examples/widgets/desktop/screenshot/screenshot.h index 352806cdba8f4b2527a6277768d379707fc558a7..f0e737e4c7b4c84e337377fb2dd36336b9f97832 100644 --- a/examples/widgets/desktop/screenshot/screenshot.h +++ b/examples/widgets/desktop/screenshot/screenshot.h @@ -73,25 +73,14 @@ private slots: void updateCheckBox(); private: - void createOptionsGroupBox(); - void createButtonsLayout(); - QPushButton *createButton(const QString &text, QWidget *receiver, const char *member); void updateScreenshotLabel(); QPixmap originalPixmap; QLabel *screenshotLabel; - QGroupBox *optionsGroupBox; QSpinBox *delaySpinBox; - QLabel *delaySpinBoxLabel; QCheckBox *hideThisWindowCheckBox; QPushButton *newScreenshotButton; - QPushButton *saveScreenshotButton; - QPushButton *quitScreenshotButton; - - QVBoxLayout *mainLayout; - QGridLayout *optionsGroupBoxLayout; - QHBoxLayout *buttonsLayout; }; //! [0] diff --git a/examples/widgets/doc/src/screenshot.qdoc b/examples/widgets/doc/src/screenshot.qdoc index 32c4df9ec2640120c7222e1b17b7c4ae665b6f26..b376b6ce0e3d4eebe237102d42d5dd5559b864e8 100644 --- a/examples/widgets/doc/src/screenshot.qdoc +++ b/examples/widgets/doc/src/screenshot.qdoc @@ -33,7 +33,7 @@ desktop. \brief The Screenshot example shows how to take a screenshot of the - desktop using QApplication and QDesktopWidget. It also shows how + 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. @@ -73,12 +73,9 @@ \uicontrol {Hide This Window} option. \endlist - We also declare some private functions: We use the \c - createOptionsGroupBox(), \c createButtonsLayout() and \c - createButton() functions when we construct the widget. And we call - the private \c updateScreenshotLabel() function whenever a new - screenshot is taken or when a resize event changes the size of the - screenshot preview label. + 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 @@ -100,11 +97,18 @@ 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. + suitable size depending on the screen geometry. \snippet desktop/screenshot/screenshot.cpp 1 @@ -151,34 +155,37 @@ 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. + 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 path the application is run from. We - create the file dialog using the static - QFileDialog::getSaveFileName() function which returns a file name - selected by the user. The file does not have to exist. If 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. 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. - - The QApplication class manages the GUI application's control flow - and main settings. It contains the main event loop, where all - events from the window system and other sources are processed and - dispatched. + The \c shootScreen() slot is called to take the screenshot. - \snippet desktop/screenshot/screenshot.cpp 5 + 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. - Using the static function QApplication::primaryScreen(), we - obtain the QScreen object for the application's main screen. + 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 take the screenshot using the QScreen::grabWindow() + 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(). @@ -200,37 +207,6 @@ The \c updateCheckBox() slot is called whenever the user changes the delay using the \uicontrol {Screenshot Delay} option. - \snippet desktop/screenshot/screenshot.cpp 7 - - The private \c createOptionsGroupBox() function is called from the - constructor. - - First 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 and install the layout on the group box. - - Note that we don't have to specify any parents for the widgets - when we create them. The reason is that when we add a widget to a - layout and install the layout on another widget, the layout's - widgets are automatically reparented to the widget the layout is - installed on. - - \snippet desktop/screenshot/screenshot.cpp 8 - - The private \c createButtonsLayout() function is called from the - constructor. We create the application's buttons using the private - \c createButton() function, and add them to a QHBoxLayout. - - \snippet desktop/screenshot/screenshot.cpp 9 - - The private \c createButton() function is called from the \c - createButtonsLayout() function. It simply creates a QPushButton - with the provided text, connects it to the provided receiver and - slot, and returns a pointer to the button. - \snippet desktop/screenshot/screenshot.cpp 10 The private \c updateScreenshotLabel() function is called whenever