基于QGraphicsItem的字幕翻转动画效果

OS: mac os x 10.7.5 QT: 5.0.1

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QGraphicsScene>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    TxtItem txtItem;
    txtItem.setText("How are you, my friend!!");

    QGraphicsScene scene;
    MyQView mqv(&scene);

    scene.addItem(&txtItem);

    mqv.show();

    return a.exec();
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsView>
#include <QGraphicsItem>
#include <QTimer>

class MyQView : public QGraphicsView {
    Q_OBJECT
public:
    MyQView(QGraphicsScene *scene);
    ~MyQView();
};

class TxtItem : public QObject, public QGraphicsItem {
    Q_OBJECT
public:
    explicit TxtItem(QGraphicsItem *parent = 0);
    ~TxtItem();

   void paint(QPainter * painter,
              const QStyleOptionGraphicsItem * option,
              QWidget * widget = 0);
   QRectF boundingRect () const;
   void setText(const QString &newText);

public slots:
   void flip();

private slots:
   void animateFilp();

private:
    QTimer *tm;
    int m_angle;   //rotation angle
    int m_delta;
    int m_current; //store rotation direction
    QString m_text;
};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include <QTimer>

MyQView::MyQView(QGraphicsScene *scene) : QGraphicsView(scene) {
    setGeometry(100, 100, 800, 600);
    setWindowFlags(Qt::FramelessWindowHint);
}

MyQView::~MyQView() {

}

TxtItem::TxtItem(QGraphicsItem *parent)
    : QGraphicsItem(parent) {

    m_angle = 0;
    m_delta = 0;
    m_current = 0;
    setOpacity(0.5);

    tm = new QTimer;
    tm->setInterval(2000);
    connect(tm, SIGNAL(timeout()), this, SLOT(flip()));
    tm->start();
}

TxtItem::~TxtItem() {
    tm->stop();
    delete tm;
}

void TxtItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) {
    QBrush brush(Qt::blue);
    painter->setBrush(brush);

    painter->drawRect(boundingRect());
    painter->setPen(QPen(Qt::red, 10));
    painter->drawText(boundingRect().x(), boundingRect().y(),
                      boundingRect().width(), boundingRect().height(),
                      Qt::AlignLeft | Qt::AlignVCenter, m_text);
}

QRectF TxtItem::boundingRect() const {
    return QRectF(0, 0, 600, 300);
}

void TxtItem::setText(const QString &newText) {
    m_text = newText;
}

void TxtItem::animateFilp() {
    m_angle += m_delta;

    if(180 == m_angle) {
        m_current ^= 1;
    }

    QRectF r = boundingRect();
    setTransform(QTransform()
                 .translate(r.width() / 2, r.height() /2)
                 .rotate(m_angle, Qt::XAxis)
                 .translate(-r.width() / 2, -r.height() / 2));
    if((0 == m_current && m_angle > 0) || (1 == m_current && m_angle < 360)) {
        QTimer::singleShot(25, this, SLOT(animateFilp()));
    }
}

void TxtItem::flip() {
    m_delta = (m_current == 0 ? 9 : -9);
    animateFilp();
}