×
Namespaces

Variants
Actions

Simple turn page effect with graphics view

From Nokia Developer Wiki
Jump to: navigation, search
Article Metadata
Compatibility
Platform(s):
Symbian
Article
Created: gnuton (22 Dec 2010)
Last edited: hamishwillee (30 Jan 2013)

Contents

Introduction

This article shows how to implement turn page effect in Qt. Touchscreen devices enable developers to create more fancy and usable interfaces. A cool effect for ebook readers is the turn page effect, which could be done in several ways.

Goal

The media player is loading...

This example has been written to show you how to achieve a turn-page effect in a simple way just using the Qt graphics view. It involves simple 2D prospective transformations and gradients usage. The code shown in this article is just a proof-of-concept and it can be largely improved. This example can render just simple text, but actually it could became a PDF reader just displaying QImages rendered by some libraries such as libpoppler... The page graphics item displays two pages at same time and by sliding your finger from right to left, you can change page. To keep the code simple, few features have been implemented (indeed it's only possible to go forward). This one, as well as many other features, can be added easily.

Implementation

The idea is to have only one graphics item which shows and animate every page. This item is big as the page size, and it's able to show only 2 pages at time. This is not a limitation, but it's how the item has been designed. The first page is the page which has to be animated. The second one is the one which stays on the back and it's static. Both pages are drawn by the item paint method and the animation is done by a QVariantAnimation subclass. Mouse events are used to get the gestures, which make this implementation working in devices where QGestures are not available. The page animation is done by rotating the page around the Y axis. The page effect can be changed moving the origin along the left border of the page.

Turnpage.png

Code

Here the main class which draws the pages. The complete code can be found at the end of this page.

#ifndef PAGE_H
#define PAGE_H
 
#include <QWidget>
#include <QGraphicsRectItem>
#include <QGraphicsSceneMouseEvent>
#include <QStyleOptionGraphicsItem>
#include <myVariantAnimator.h>
#include <QPainter>
 
#include <math.h>
 
class page : public QObject, public QGraphicsRectItem
{
Q_OBJECT
public:
page(QGraphicsItem * parent = 0): mAngle(0){
 
// Set border and text foreground color
this->setPen(QPen(Qt::black));
 
// Set size
mWidth = 200; //Sorry this has been hard-coded to make the code minimal
mHeight = sqrt(2)* mWidth;
this->setRect(QRect(0,-mHeight/2, mWidth, mHeight));
 
//Initialize the animator
mAngleAnimator.setStartValue(0);
mAngleAnimator.setEndValue(90);
mAngleAnimator.setDuration(1000);
mAngleAnimator.setEasingCurve(QEasingCurve::Linear);
connect(&mAngleAnimator, SIGNAL(valueChanged(const QVariant&)), this, SLOT(doAnimation()));
}
 
void mousePressEvent(QGraphicsSceneMouseEvent *event){
mX = event->pos().x();
}
 
void mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
// Change page
int currentX = event->pos().x();
if ((mX - currentX) > (mWidth/3)){
mAngleAnimator.start();
}
}
 
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0){
Q_UNUSED(widget);
 
int angle = 0;
painter->setPen(QPen(Qt::black));
 
// Draw the page on the back
renderPage(painter, angle);
 
// Draw the page on the front
painter->save();
 
angle = mAngleAnimator.currentValue().toInt();
 
QTransform t;
t.rotate(angle, Qt::YAxis);
painter->setTransform(t, true);
 
renderPage(painter, angle);
 
painter->restore();
}
 
void setText(const QString& text){
mText = text;
}
 
const QString text(){
return mText;
}
 
private:
 
inline void renderPage(QPainter* painter, int angle){
QLinearGradient fade;
fade.setColorAt(0, QColor(148,148,148, 255));
fade.setColorAt(1, QColor(255, 255, 255, 255));
fade.setStart(0, mHeight/2);
 
fade.setFinalStop(mWidth * calcGradient(angle), mHeight/2);;
painter->fillRect(boundingRect(), fade);
painter->drawRect(boundingRect());
painter->drawText(boundingRect(), mText);
}
 
inline qreal calcGradient(int angle){
qreal x1 = 0; // Initial angle
qreal y1 = (qreal)1/15; // shadow width at the initial angle
qreal x2 = 90; // Final angle
qreal y2 = 1; // shadow width at the final angle
qreal q = y1;
 
return (y2 - y1)/(x2 - x1) * angle + q;
}
 
public slots:
void doAnimation(){
update(boundingRect());
}
 
private:
int mWidth;
int mHeight;
int mX;
int mAngle;
myVariantAnimator mAngleAnimator;
 
QString mText;
};
 
#endif // PAGE_H
This page was last modified on 30 January 2013, at 07:25.
56 page views in the last 30 days.

Was this page helpful?

Your feedback about this content is important. Let us know what you think.

 

Thank you!

We appreciate your feedback.

×