Einen Screenshot erstellen
Das Beispiel „Screenshot“ zeigt, wie man einen Screenshot des Desktops erstellt.

Mit der Anwendung können die Benutzer einen Screenshot ihres Desktops erstellen. Dabei stehen ihnen mehrere Optionen zur Verfügung:
- Den Screenshot verzögern, damit sie Zeit haben, ihren Desktop neu zu ordnen.
- Das Fenster der Anwendung während der Erstellung des Screenshots ausblenden.
Darüber hinaus ermöglicht die Anwendung den Benutzern, ihren Screenshot zu speichern, wenn sie dies wünschen.
Definition der Screenshot-Klasse
class Screenshot : public QWidget
{
Q_OBJECT
public:
Screenshot();
protected:
void resizeEvent(QResizeEvent *event) override;
private slots:
void newScreenshot();
void saveScreenshot();
void shootScreen();
void updateCheckBox();
private:
void updateScreenshotLabel();
QPixmap originalPixmap;
QLabel *screenshotLabel;
QSpinBox *delaySpinBox;
QCheckBox *hideThisWindowCheckBox;
QPushButton *newScreenshotButton;
QPushButton *saveScreenshotButton;
};Die Klasse „ Screenshot “ erbt von „ QWidget “ und ist das Haupt-Widget der Anwendung. Sie zeigt die Anwendungsoptionen und eine Vorschau des Screenshots an.
Wir implementieren die Funktion ` QWidget::resizeEvent()` neu, um sicherzustellen, dass die Vorschau des Screenshots korrekt skaliert wird, wenn der Benutzer die Größe des Anwendungs-Widgets ändert. Außerdem benötigen wir mehrere private Slots, um die Optionen zu ermöglichen:
- Der Slot „
newScreenshot()“ bereitet einen neuen Screenshot vor. - Der Slot „
saveScreenshot()“ speichert den letzten Screenshot. - Der Slot „
shootScreen()“ erstellt den Screenshot. - Der Slot „
updateCheckBox()“ aktiviert oder deaktiviert die Option „ Hide This Window “.
Außerdem deklarieren wir die private Funktion „ updateScreenshotLabel() “, die immer dann aufgerufen wird, wenn ein neuer Screenshot aufgenommen wird oder wenn ein Resize-Ereignis die Größe der Vorschau des Screenshots ändert.
Zudem müssen wir die ursprüngliche Pixmap des Screenshots speichern. Der Grund dafür ist, dass wir bei der Anzeige der Vorschau des Screenshots dessen Pixmap skalieren müssen; durch das Speichern des Originals stellen wir sicher, dass dabei keine Daten verloren gehen.
Implementierung der Screenshot-Klasse
Screenshot::Screenshot()
: screenshotLabel(new QLabel(this))
{
screenshotLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
screenshotLabel->setAlignment(Qt::AlignCenter);
const QRect screenGeometry = screen()->geometry();
screenshotLabel->setMinimumSize(screenGeometry.width() / 8, screenGeometry.height() / 8);
screenshotLabel->setFrameShape(QFrame::Box);
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);
connect(delaySpinBox, &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);
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);
shootScreen();
delaySpinBox->setValue(5);
setWindowTitle(tr("Screenshot"));
resize(300, 200);
}Im Konstruktor erstellen wir zunächst das ` QLabel `, das die Screenshot-Vorschau anzeigt.
Wir legen die Größenrichtlinie des „ QLabel “ sowohl horizontal als auch vertikal auf „ QSizePolicy::Expanding “ fest. Das bedeutet, dass der Größenhinweis des „ QLabel “ eine sinnvolle Größe angibt, das Widget jedoch verkleinert werden kann und dennoch nützlich bleibt. Außerdem kann das Widget zusätzlichen Platz nutzen, daher sollte es so viel Platz wie möglich erhalten. Anschließend stellen wir sicher, dass das „ QLabel “ in der Mitte des „ Screenshot “-Widgets ausgerichtet ist, und legen dessen Mindestgröße fest.
Als Nächstes erstellen wir ein Gruppenfeld, das alle Widgets der Optionen enthalten wird. Dann erstellen wir ein „ QSpinBox “ und ein „ QLabel “ für die Option „ Screenshot Delay “ und verbinden das „spinbox“-Widget mit dem „ updateCheckBox() “-Slot. Schließlich erstellen wir ein „ QCheckBox “ für die Option „ Hide This Window “ und fügen alle Widgets der Optionen zu einem „ QGridLayout “ hinzu, das auf dem Gruppenfeld installiert ist.
Wir erstellen die Schaltflächen der Anwendung sowie die Gruppenbox, die die Optionen der Anwendung enthält, und fügen alles in ein Hauptlayout ein. Schließlich nehmen wir den anfänglichen Screenshot auf, legen die anfängliche Verzögerung und den Fenstertitel fest, bevor wir die Größe des Widgets entsprechend der Bildschirmgeometrie anpassen.
void Screenshot::resizeEvent(QResizeEvent * /* event */)
{
if (!originalPixmap.isNull()) {
QSize scaledSize = originalPixmap.size();
scaledSize.scale(screenshotLabel->size(), Qt::KeepAspectRatio);
if (scaledSize != screenshotLabel->pixmap().size())
updateScreenshotLabel();
}
}Die Funktion ` resizeEvent() ` wird neu implementiert, um die an das Widget gesendeten Größenänderungsereignisse zu empfangen. Ziel ist es, die Pixmap des Vorschaubildschirms ohne Verzerrung ihres Inhalts zu skalieren und sicherzustellen, dass die Größe der Anwendung reibungslos angepasst werden kann.
Um das erste Ziel zu erreichen, skalieren wir die Screenshot-Pixmap mithilfe von ` Qt::KeepAspectRatio`. Wir skalieren die Pixmap auf ein Rechteck, das innerhalb der aktuellen Größe des Vorschau-Labels so groß wie möglich ist, wobei das Seitenverhältnis beibehalten wird. Das bedeutet: Wenn der Benutzer die Größe des Anwendungsfensters nur in eine Richtung ändert, behält der Vorschau-Screenshot dieselbe Größe bei.
Um unser zweites Ziel zu erreichen, stellen wir sicher, dass der Vorschaubild-Screenshot nur dann neu gezeichnet wird (mithilfe der privaten Funktion „ updateScreenshotLabel() “), wenn sich seine Größe tatsächlich ändert.
void Screenshot::newScreenshot()
{
if (hideThisWindowCheckBox->isChecked())
hide();
newScreenshotButton->setDisabled(true);
QTimer::singleShot(delaySpinBox->value() * 1000, this, &Screenshot::shootScreen);
}Der private Slot „ newScreenshot() “ wird aufgerufen, wenn der Benutzer einen neuen Screenshot anfordert; der Slot bereitet jedoch lediglich einen neuen Screenshot vor.
Zunächst prüfen wir, ob die Option „ Hide This Window “ aktiviert ist; ist dies der Fall, blenden wir das Widget „ Screenshot “ aus. Anschließend deaktivieren wir die Schaltfläche „ New Screenshot “, um sicherzustellen, dass der Benutzer jeweils nur einen Screenshot anfordern kann.
Wir erstellen einen Timer mithilfe der Klasse „ QTimer “, die sowohl wiederholbare als auch einmalige Timer bereitstellt. Wir stellen den Timer so ein, dass er nur einmal abläuft, und zwar mithilfe der statischen Funktion „ QTimer::singleShot()“. Diese Funktion ruft den privaten Slot „ shootScreen() “ auf, nachdem das durch die Option „ Screenshot Delay “ festgelegte Zeitintervall abgelaufen ist. Es ist „ shootScreen() “, das den Screenshot tatsächlich ausführt.
void Screenshot::saveScreenshot()
{
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;
const QList<QByteArray> baMimeTypes = QImageWriter::supportedMimeTypes();
for (const QByteArray &bf : baMimeTypes)
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)));
}
}Der Slot „ saveScreenshot() “ wird aufgerufen, wenn der Benutzer die Schaltfläche „ Save “ betätigt, und er zeigt mithilfe der Klasse „ QFileDialog “ einen Dateidialog an.
QFileDialog ermöglicht es dem Benutzer, das Dateisystem zu durchsuchen, um eine oder mehrere Dateien oder ein Verzeichnis auszuwählen. Der einfachste Weg, einen „ QFileDialog “ zu erstellen, ist die Verwendung der statischen Hilfsfunktionen. Hier instanziieren wir den Dialog auf dem Stack, um die unterstützten MIME-Typen von „ QImageWriter “ einrichten zu können, sodass der Benutzer in einer Vielzahl von Formaten speichern kann.
QStandardPathsWir legen das Standarddateiformat auf „png“ fest und setzen den Anfangspfad des Dateidialogs auf den Speicherort der Bilder, wie er von abgerufen wird; standardmäßig ist dies der Pfad, aus dem die Anwendung ausgeführt wird.
Wir rufen den Dialog auf, indem wir ` QDialog::exec()` aufrufen, und kehren zurück, falls der Benutzer den Dialog abgebrochen hat. Wurde der Dialog akzeptiert, ermitteln wir einen Dateinamen durch Aufruf von ` QFileDialog::selectedFiles()`. Die Datei muss nicht vorhanden sein. Ist der Dateiname gültig, verwenden wir die Funktion ` QPixmap::save()`, um die ursprüngliche Pixmap des Screenshots in dieser Datei zu speichern.
void Screenshot::shootScreen()
{
if (delaySpinBox->value() != 0)
QApplication::beep();
originalPixmap = screen()->grabWindow(0);
updateScreenshotLabel();
newScreenshotButton->setDisabled(false);
if (hideThisWindowCheckBox->isChecked())
show();
}Der Slot „ shootScreen() “ wird aufgerufen, um den Screenshot aufzunehmen.
Wenn der Benutzer eine Verzögerung beim Erstellen des Screenshots gewählt hat, lassen wir die Anwendung einen Signalton ausgeben, sobald der Screenshot mithilfe der statischen Funktion ` QApplication::beep()` aufgenommen wird.
Anschließend erstellen wir den Screenshot mithilfe der Funktion ` QScreen::grabWindow()` auf dem von ` QWidget::screen()` zurückgegebenen Bildschirm. Die Funktion erfasst den Inhalt des als Argument übergebenen Fensters, erstellt daraus eine Pixmap und gibt diese zurück. Die Fenster-ID kann mit ` QWidget::winId()` oder ` QWindow::winId()` ermittelt werden. Hier übergeben wir jedoch einfach 0 als Fenster-ID, was angibt, dass wir den gesamten Bildschirm erfassen möchten.
Wir aktualisieren die Beschriftung der Screenshot-Vorschau mithilfe der privaten Funktion ` updateScreenshotLabel() `. Anschließend aktivieren wir die Schaltfläche „ New Screenshot “ und machen schließlich das Widget ` Screenshot ` wieder sichtbar, falls es während des Screenshots ausgeblendet war.
void Screenshot::updateCheckBox()
{
if (delaySpinBox->value() == 0) {
hideThisWindowCheckBox->setDisabled(true);
hideThisWindowCheckBox->setChecked(false);
} else {
hideThisWindowCheckBox->setDisabled(false);
}
}Die Option „ Hide This Window “ wird je nach Verzögerung des Screenshots aktiviert oder deaktiviert. Wenn keine Verzögerung vorliegt, kann das Anwendungsfenster nicht ausgeblendet werden und das Kontrollkästchen der Option ist deaktiviert.
Der Slot „ updateCheckBox() “ wird immer dann aufgerufen, wenn der Benutzer die Verzögerung über die Option „ Screenshot Delay “ ändert.
void Screenshot::updateScreenshotLabel()
{
if (originalPixmap.isNull()) {
saveScreenshotButton->setEnabled(false);
screenshotLabel->setText(tr("Grabbing \"%1\" failed.").arg(screen()->name()));
} else {
saveScreenshotButton->setEnabled(true);
screenshotLabel->setPixmap(originalPixmap.scaled(screenshotLabel->size(),
Qt::KeepAspectRatio,
Qt::SmoothTransformation));
}
}Die private Funktion „ updateScreenshotLabel() “ wird immer dann aufgerufen, wenn sich der Screenshot ändert oder wenn ein Resize-Ereignis die Größe der Vorschau-Beschriftung des Screenshots verändert.
Zunächst behandeln wir den Fehlerfall. Auf einigen Plattformen, insbesondere Wayland, ist es nicht möglich, den Bildschirminhalt abzurufen. In diesem Fall ist die Pixmap leer, wie durch ` QPixmap::isNull()` angezeigt wird. Wir setzen eine Fehlermeldung auf das Label und deaktivieren die Schaltfläche zum Speichern.
Wenn eine Pixmap abgerufen wurde, aktualisieren wir die Beschriftung der Screenshot-Vorschau mithilfe der Funktionen „ QLabel::setPixmap()“ und „ QPixmap::scaled()“.
QPixmap::scaled() gibt eine Kopie der angegebenen Pixmap zurück, die entsprechend den angegebenen Werten für ` Qt::AspectRatioMode ` und ` Qt::TransformationMode` auf ein Rechteck der angegebenen Größe skaliert wurde.
Wir skalieren die ursprüngliche Pixmap so, dass sie in die Größe der aktuellen Screenshot-Beschriftung passt, wobei das Seitenverhältnis beibehalten wird und die resultierende Pixmap geglättete Kanten erhält.
© 2026 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.