一、思路
使用Qt的Graphics View Framework可以非常容易实现翻转的效果。该框架中的item可以通过设置QGraphicsRotation实现沿x轴、y轴和z轴(垂直于屏幕)方向上的旋转。再配合上动画便能达到上图的效果。
二、关键代码
1.既然是基于图形视图框架,那view是必不可少的。从基类中派生出我们的视图类FlipView:
FlipView : public QGraphicsView在这个demo中视图和场景都不是主角。场景无需做其他设置,视图也只是做了一些简单的设置即可。
FlipView::FlipView(QWidget *parent):QGraphicsView(parent) { //场景 m_pScne = new QGraphicsScene(); this->setScene(m_pScne); //item m_picture = new Picture(); m_pScne->addItem(m_picture); //设置 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setViewportUpdateMode(FullViewportUpdate); //刷新方式 setCacheMode(CacheBackground); setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); } void FlipView::drawBackground(QPainter *painter, const QRectF &rect) { //重写drawBackground函数绘制视图的背景 painter->drawPixmap(rect,QPixmap(":/back.jpg"),QRectF()); } void FlipView::resizeEvent(QResizeEvent *event) { //在视图大小变化时,让Item填充视图(缩放) fitInView(m_picture, Qt::KeepAspectRatioByExpanding); }2.demo的主角,图片Item从QGraphicsObject中派生,其主要成员变量如下:
class Picture : public QGraphicsObject //主要成员变量: QList<QPixmap> m_pixmaplist; //图片列表 int m_index; //当前显示的图片的下标 QPropertyAnimation* m_roateAnimation; //m_itemRotation的动画 QParallelAnimationGroup* m_animationGroup; //并行动画组,包括m_rotateAnimation和item的缩放动画 QGraphicsRotation* m_itemRotation; //旋转在构造函数中做设置变换:
Picture::Picture(QGraphicsItem *parent):QGraphicsObject(parent) { //初始化 m_pixmaplist.append(QPixmap(":/01.jpg")); m_pixmaplist.append(QPixmap(":/02.jpg")); m_index = 0; m_bChanged = false; //设置该item的变换 m_itemRotation = new QGraphicsRotation(this); m_itemRotation->setAxis(Qt::YAxis); //沿Y轴旋转 m_itemRotation->setOrigin(QVector3D(boundingRect().width()/2,0,0)); //旋转基准位置为item的中心线 this->setTransformations(QList<QGraphicsTransform *>()<<m_itemRotation);//<--关键--> //动画效果 m_roateAnimation = new QPropertyAnimation(m_itemRotation, "angle"); //动画与m_itemRotation绑定 m_roateAnimation->setDuration(1500); connect(m_roateAnimation,SIGNAL(finished()),this,SLOT(animationFinished())); connect(m_roateAnimation,SIGNAL(valueChanged(QVariant)),this,SLOT(animationValueChanged(QVariant))); QPropertyAnimation* scaleAnimation = new QPropertyAnimation(this,"scale"); //辅助效果,让item翻转的时候先缩小再放大 scaleAnimation->setDuration(1500); scaleAnimation->setStartValue(1); scaleAnimation->setKeyValueAt(0.5,0.3); scaleAnimation->setEndValue(1); setTransformOriginPoint(this->boundingRect().center()); m_animationGroup = new QParallelAnimationGroup(this); m_animationGroup->addAnimation(m_roateAnimation); m_animationGroup->addAnimation(scaleAnimation); }在构造函数中的设置已经能够实现图片的翻转效果,为了让翻转效果更逼真,我们在旋转到90度左右(图片与屏幕垂直)时换一张图片显示,好像两张图片刚好是正反两面。
在旋转动画的槽函数中进行判断:
void Picture::animationValueChanged(const QVariant &value){ if(!m_bChanged){ if(value.toDouble() >= 90 - 2 && value.toDouble() <= 90 + 2){ //旋转角度约在90度左右时切换当前图片下标 if(++m_index >= m_pixmaplist.count()){ m_index = 0; } m_bChanged = true; //一次旋转动画只需要判断一次是否到90度即可。 update(); } } }
点击查看原文
