From c7ba279815f9bd35a78ede33f516583cf8b022ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= <samuel.rodal@nokia.com> Date: Wed, 23 Nov 2011 09:36:51 +0100 Subject: [PATCH] Added rotation animation to paintedwindow example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This serves as a useful test case for the QScreen orientation API. Change-Id: I009ebd8b6d345453620420d84f3ff9d2d2e2663e Reviewed-by: Jørgen Lind <jorgen.lind@nokia.com> --- examples/opengl/paintedwindow/main.cpp | 3 +- .../opengl/paintedwindow/paintedwindow.cpp | 135 +++++++++++++++--- examples/opengl/paintedwindow/paintedwindow.h | 26 ++++ 3 files changed, 141 insertions(+), 23 deletions(-) diff --git a/examples/opengl/paintedwindow/main.cpp b/examples/opengl/paintedwindow/main.cpp index d4eead9d402..c672798558e 100644 --- a/examples/opengl/paintedwindow/main.cpp +++ b/examples/opengl/paintedwindow/main.cpp @@ -53,7 +53,7 @@ int main(int argc, char **argv) QRect screenGeometry = screen->availableGeometry(); QPoint center = screenGeometry.center(); - QRect windowRect(0, 0, 640, 480); + QRect windowRect(0, 0, 480, 640); PaintedWindow window; window.setGeometry(QRect(center - windowRect.center(), windowRect.size())); @@ -61,3 +61,4 @@ int main(int argc, char **argv) app.exec(); } + diff --git a/examples/opengl/paintedwindow/paintedwindow.cpp b/examples/opengl/paintedwindow/paintedwindow.cpp index 543c13eab30..78539d7ff17 100644 --- a/examples/opengl/paintedwindow/paintedwindow.cpp +++ b/examples/opengl/paintedwindow/paintedwindow.cpp @@ -64,6 +64,21 @@ PaintedWindow::PaintedWindow() m_context = new QOpenGLContext(this); m_context->setFormat(format); m_context->create(); + + m_animation = new QPropertyAnimation(this, "rotation"); + m_animation->setStartValue(qreal(0)); + m_animation->setEndValue(qreal(1)); + m_animation->setDuration(500); + + setOrientation(QGuiApplication::primaryScreen()->primaryOrientation()); + m_rotation = 0; + + m_targetOrientation = orientation(); + m_nextTargetOrientation = Qt::UnknownOrientation; + + connect(screen(), SIGNAL(currentOrientationChanged(Qt::ScreenOrientation)), this, SLOT(orientationChanged(Qt::ScreenOrientation))); + connect(m_animation, SIGNAL(finished()), this, SLOT(rotationDone())); + connect(this, SIGNAL(rotationChanged(qreal)), this, SLOT(paint())); } void PaintedWindow::resizeEvent(QResizeEvent *) @@ -79,21 +94,18 @@ void PaintedWindow::exposeEvent(QExposeEvent *) void PaintedWindow::mousePressEvent(QMouseEvent *) { Qt::ScreenOrientation o = orientation(); - if (o == Qt::UnknownOrientation) - o = QGuiApplication::primaryScreen()->primaryOrientation(); - switch (o) { case Qt::LandscapeOrientation: - setOrientation(Qt::PortraitOrientation); + orientationChanged(Qt::PortraitOrientation); break; case Qt::PortraitOrientation: - setOrientation(Qt::InvertedLandscapeOrientation); + orientationChanged(Qt::InvertedLandscapeOrientation); break; case Qt::InvertedLandscapeOrientation: - setOrientation(Qt::InvertedPortraitOrientation); + orientationChanged(Qt::InvertedPortraitOrientation); break; case Qt::InvertedPortraitOrientation: - setOrientation(Qt::LandscapeOrientation); + orientationChanged(Qt::LandscapeOrientation); break; default: Q_ASSERT(false); @@ -102,31 +114,110 @@ void PaintedWindow::mousePressEvent(QMouseEvent *) paint(); } +void PaintedWindow::orientationChanged(Qt::ScreenOrientation newOrientation) +{ + if (orientation() == newOrientation) + return; + + if (m_animation->state() == QAbstractAnimation::Running) { + m_nextTargetOrientation = newOrientation; + return; + } + + Qt::ScreenOrientation screenOrientation = screen()->primaryOrientation(); + + QRect rect(0, 0, width(), height()); + + m_prevImage = QImage(width(), height(), QImage::Format_ARGB32_Premultiplied); + m_nextImage = QImage(width(), height(), QImage::Format_ARGB32_Premultiplied); + m_prevImage.fill(0); + m_nextImage.fill(0); + + QPainter p; + p.begin(&m_prevImage); + p.setTransform(QScreen::transformBetween(orientation(), screenOrientation, rect)); + paint(&p, QScreen::mapBetween(orientation(), screenOrientation, rect)); + p.end(); + + p.begin(&m_nextImage); + p.setTransform(QScreen::transformBetween(newOrientation, screenOrientation, rect)); + paint(&p, QScreen::mapBetween(newOrientation, screenOrientation, rect)); + p.end(); + + m_deltaRotation = QScreen::angleBetween(newOrientation, orientation()); + if (m_deltaRotation > 180) + m_deltaRotation = 180 - m_deltaRotation; + + m_targetOrientation = newOrientation; + m_animation->start(); +} + +void PaintedWindow::rotationDone() +{ + setOrientation(m_targetOrientation); + if (m_nextTargetOrientation != Qt::UnknownOrientation) { + Q_ASSERT(m_animation->state() != QAbstractAnimation::Running); + orientationChanged(m_nextTargetOrientation); + m_nextTargetOrientation = Qt::UnknownOrientation; + } +} + +void PaintedWindow::setRotation(qreal r) +{ + if (r != m_rotation) { + m_rotation = r; + emit rotationChanged(r); + } +} + void PaintedWindow::paint() { m_context->makeCurrent(this); - QOpenGLPaintDevice device(size()); - - Qt::ScreenOrientation screenOrientation = QGuiApplication::primaryScreen()->primaryOrientation(); + Qt::ScreenOrientation screenOrientation = screen()->primaryOrientation(); Qt::ScreenOrientation appOrientation = orientation(); QRect rect(0, 0, width(), height()); - QRect mapped = QScreen::mapBetween(appOrientation, screenOrientation, rect); - - QPainterPath path; - path.addEllipse(mapped); + QOpenGLPaintDevice device(size()); QPainter painter(&device); - painter.setTransform(QScreen::transformBetween(appOrientation, screenOrientation, rect)); - painter.fillRect(mapped, Qt::white); - painter.setRenderHint(QPainter::Antialiasing); + + QPainterPath path; + path.addEllipse(rect); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(rect, Qt::transparent); + painter.setCompositionMode(QPainter::CompositionMode_SourceOver); painter.fillPath(path, Qt::blue); - QFont font; - font.setPixelSize(64); - painter.setFont(font); - painter.drawText(mapped, Qt::AlignCenter, "Hello"); - painter.end(); + + if (orientation() != m_targetOrientation) { + painter.setRenderHint(QPainter::SmoothPixmapTransform); + painter.save(); + painter.translate(width() / 2, height() / 2); + painter.rotate(m_deltaRotation * m_rotation); + painter.translate(-width() / 2, -height() / 2); + painter.drawImage(0, 0, m_prevImage); + painter.restore(); + painter.translate(width() / 2, height() / 2); + painter.rotate(m_deltaRotation * m_rotation - m_deltaRotation); + painter.translate(-width() / 2, -height() / 2); + painter.setOpacity(m_rotation); + painter.drawImage(0, 0, m_nextImage); + } else { + QRect mapped = QScreen::mapBetween(appOrientation, screenOrientation, rect); + + painter.setTransform(QScreen::transformBetween(appOrientation, screenOrientation, rect)); + paint(&painter, mapped); + painter.end(); + } m_context->swapBuffers(this); } + +void PaintedWindow::paint(QPainter *painter, const QRect &rect) +{ + painter->setRenderHint(QPainter::Antialiasing); + QFont font; + font.setPixelSize(64); + painter->setFont(font); + painter->drawText(rect, Qt::AlignCenter, "Hello"); +} diff --git a/examples/opengl/paintedwindow/paintedwindow.h b/examples/opengl/paintedwindow/paintedwindow.h index dcf8110e245..28e06ec4df1 100644 --- a/examples/opengl/paintedwindow/paintedwindow.h +++ b/examples/opengl/paintedwindow/paintedwindow.h @@ -44,7 +44,10 @@ #include <QtGui/qopenglshaderprogram.h> #include <QtGui/qopenglframebufferobject.h> +#include <QPropertyAnimation> + #include <QColor> +#include <QImage> #include <QTime> QT_BEGIN_NAMESPACE @@ -54,16 +57,39 @@ QT_END_NAMESPACE class PaintedWindow : public QWindow { Q_OBJECT + Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged) + public: PaintedWindow(); + qreal rotation() const { return m_rotation; } + +signals: + void rotationChanged(qreal rotation); + private slots: void paint(); + void setRotation(qreal r); + void orientationChanged(Qt::ScreenOrientation newOrientation); + void rotationDone(); private: void resizeEvent(QResizeEvent *); void exposeEvent(QExposeEvent *); void mousePressEvent(QMouseEvent *); + void paint(QPainter *painter, const QRect &rect); + QOpenGLContext *m_context; + qreal m_rotation; + + QImage m_prevImage; + QImage m_nextImage; + qreal m_deltaRotation; + + Qt::ScreenOrientation m_targetOrientation; + Qt::ScreenOrientation m_nextTargetOrientation; + + QPropertyAnimation *m_animation; + QTimer *m_paintTimer; }; -- GitLab