-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add QPainterStateGuard as a small RAII helper class to avoid unbalanced QPainter::save()/restore() calls. Change-Id: I618a5d720b7bc9267a0fbac7dcc90e61f5d9cefd Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> Reviewed-by: David Faure <david.faure@kdab.com>
- Loading branch information
Showing
4 changed files
with
167 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
54 changes: 54 additions & 0 deletions
54
src/gui/doc/snippets/code/src_gui_painting_qpainterstateguard.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
// Copyright (C) 2024 Christian Ehrlicher <ch.ehrlicher@gmx.de> | ||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause | ||
#include <QPaintEvent> | ||
#include <QPainter> | ||
#include <QPainterStateGuard> | ||
#include <QWidget> | ||
|
||
|
||
namespace src_gui_painting_qpainterstateguard { | ||
struct MyWidget : public QWidget | ||
{ | ||
void paintEvent(QPaintEvent *) override; | ||
bool drawText = true; | ||
QLine line; | ||
}; | ||
struct MyGuardWidget : public QWidget | ||
{ | ||
void paintEvent(QPaintEvent *) override; | ||
bool drawText = true; | ||
QLine line; | ||
}; | ||
|
||
//! [0] | ||
void MyWidget::paintEvent(QPaintEvent *) | ||
{ | ||
QPainter painter(this); | ||
painter.setPen(Qt::red); | ||
if (drawText) { | ||
painter.save(); | ||
painter.setPen(Qt::blue); | ||
painter.setFont(QFont("Arial", 30)); | ||
painter.drawText(rect(), Qt::AlignCenter, "Qt"); | ||
painter.restore(); // don't forget to restore previous painter state | ||
} | ||
painter.drawLine(line); | ||
} | ||
//! [0] | ||
|
||
//! [1] | ||
void MyGuardWidget::paintEvent(QPaintEvent *) | ||
{ | ||
QPainter painter(this); | ||
painter.setPen(Qt::red); | ||
if (drawText) { | ||
QPainterStateGuard guard(&painter) | ||
painter.setPen(Qt::blue); | ||
painter.setFont(QFont("Arial", 30)); | ||
painter.drawText(rect(), Qt::AlignCenter, "Qt"); | ||
} | ||
painter.drawLine(line); | ||
} | ||
//! [1] | ||
|
||
} // src_gui_painting_qpainterstateguard |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
// Copyright (C) 2024 Christian Ehrlicher <ch.ehrlicher@gmx.de> | ||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | ||
|
||
#include "qpainterstateguard.h" | ||
|
||
QT_BEGIN_NAMESPACE | ||
|
||
/*! | ||
\class QPainterStateGuard | ||
\brief The QPainterStateGuard is a RAII convenience class for balanced | ||
QPainter::save() and QPainter::restore() calls. | ||
\since 6.9 | ||
\inmodule QtGui | ||
\ingroup painting | ||
\reentrant | ||
\sa QPainter | ||
QPainterStateGuard should be used everywhere as a replacement for QPainter::save() | ||
to make sure that the corresponding QPainter::restore() is called upon finishing | ||
of the painting routine to avoid unbalanced calls between those two functions. | ||
Example with QPainter::save()/QPainter::restore(): | ||
\snippet code/src_gui_painting_qpainterstateguard.cpp 0 | ||
Example with QPainterStateGuard: | ||
\snippet code/src_gui_painting_qpainterstateguard.cpp 1 | ||
*/ | ||
|
||
/*! | ||
\fn QPainterStateGuard::QPainterStateGuard(QPainter *painter, InitialState state = Save) | ||
Constructs a QPainterStateGuard and calls save() on \a painter if \a state | ||
is \c Save (which is the default). When QPainterStateGuard is destroyed, restore() | ||
is called as often as save() was called to restore the QPainter's state. | ||
*/ | ||
|
||
/*! | ||
\fn QPainterStateGuard::~QPainterStateGuard() | ||
Destroys the QPainterStateGuard instance and calls restore() as often as save() | ||
was called to restore the QPainter's state. | ||
*/ | ||
|
||
/*! | ||
\fn void QPainterStateGuard::save() | ||
Calls QPainter::save() and increases the internal save/restore counter by one. | ||
*/ | ||
|
||
/*! | ||
\fn void QPainterStateGuard::restore() | ||
Calls QPainter::restore() if the internal save/restore counter is greater than zero. | ||
*/ | ||
|
||
QT_END_NAMESPACE |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
// Copyright (C) 2024 Christian Ehrlicher <ch.ehrlicher@gmx.de> | ||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only | ||
|
||
#ifndef QPAINTERSTATEGUARD_H | ||
#define QPAINTERSTATEGUARD_H | ||
|
||
#include <QtCore/qtclasshelpermacros.h> | ||
#include <QtGui/qpainter.h> | ||
|
||
QT_BEGIN_NAMESPACE | ||
|
||
class QPainterStateGuard | ||
{ | ||
Q_DISABLE_COPY_MOVE(QPainterStateGuard) | ||
public: | ||
enum InitialState | ||
{ | ||
Save, | ||
NoSave, | ||
}; | ||
|
||
Q_NODISCARD_CTOR | ||
explicit QPainterStateGuard(QPainter *painter, InitialState state = Save) | ||
: m_painter(painter) | ||
{ | ||
Q_ASSERT(painter); | ||
if (state == InitialState::Save) | ||
save(); | ||
} | ||
|
||
~QPainterStateGuard() | ||
{ | ||
while (m_level > 0) | ||
restore(); | ||
} | ||
|
||
void save() | ||
{ | ||
m_painter->save(); | ||
++m_level; | ||
} | ||
|
||
void restore() | ||
{ | ||
Q_ASSERT(m_level > 0); | ||
--m_level; | ||
m_painter->restore(); | ||
} | ||
|
||
private: | ||
QPainter *m_painter; | ||
int m_level = 0; | ||
}; | ||
|
||
QT_END_NAMESPACE | ||
|
||
#endif // QPAINTERSTATEGUARD_H |