前段时间用QGraphics框架实现过qq的翻转效果,当时也提到过其实这个功能还可以用QPainter来实现,原因是因为QPainter同样支持QTransform的
转换操作。另外一个知识点就是,QWidget窗体在paintEvent中可以通过QWidget::render(QPainter *,QPoint offset,QRegion sourceRegion)函数画出来,这样
如果我们再接合QPropertyAnimation不难实现翻转效果。
代码如下
#define TRANSFORMWIDGET_H
#include <QWidget>#include <QMap>QT_FORWARD_DECLARE_CLASS(QPropertyAnimation)
class TransformWidget : public QWidget{Q_OBJECTQ_PROPERTY(qreal tranformY READ tranformY WRITE setTranformY NOTIFY tranformYChanged)public:
TransformWidget(QWidget *parent = nullptr);QWidget *front() const; //前面QWidget *back() const; //后面void setFront(QWidget *front);void setBack(QWidget *back);void start();signals:
void tranformYChanged();protected:
void paintEvent(QPaintEvent *event);void setTranformY(qreal angle = 0); //旋转一定角度qreal tranformY() const;private:
qreal _angle{0};QPropertyAnimation *ani{nullptr};QMap<QString,QWidget*> _widgetMap; //保存前后两面QWidge指针};#endif // TRANSFORMWIDGET_H#include "transformwidget.h"
#include <QTransform>#include <QPainter>#include <QDebug>#include <QPropertyAnimation>#include <QPaintEvent>TransformWidget::TransformWidget(QWidget *parent):QWidget(parent){ani = new QPropertyAnimation(this,"tranformY",this);ani->setDuration(3000);ani->setStartValue(0);ani->setEndValue(180);ani->setEasingCurve(QEasingCurve::InCurve);connect(ani,&QPropertyAnimation::finished,[&]{ani->setDirection(QPropertyAnimation::Direction(!ani->direction()));});}void TransformWidget::setFront(QWidget *front){if(!front)return;_widgetMap["front"] = front; //添加前窗体}void TransformWidget::setBack(QWidget *back){if(!back)return;_widgetMap["back"] = back; //添加后窗体}void TransformWidget::setTranformY(qreal angle){if(_widgetMap.count() != 2){qDebug() << "please ensure you has been set front and back Widget";return;}
if(angle != _angle)emit tranformYChanged();_angle = angle;update();
}qreal TransformWidget::tranformY() const{return _angle;}void TransformWidget::paintEvent(QPaintEvent *event){QWidget *w{nullptr};if(_angle > 90){ //以90度为基准w = _widgetMap.value("back");}else{w = _widgetMap.value("front");}
QPainter painter(this);painter.setWindow(0,0,128,128); //设置painter绘图逻辑坐标,默认与this窗口一致;使其能自适应,因为视口默认与窗口一致的QTransform fm;fm.translate(w->width() >> 1,0);fm.rotate(_angle,Qt::YAxis);fm.translate(-w->width() >> 1,0);painter.setTransform(fm);
w->render(&painter);
painter.end();
return QWidget::paintEvent(event);}void TransformWidget::start(){ani->start();}在main.cpp中我们只需要添加两个窗体,并启动动画就可以了#include "widget.h"#include <QApplication>#include "transformwidget.h"#include <QLabel>#include <QTimer>#include <QDebug>int main(int argc, char *argv[]){QApplication a(argc, argv);QLabel *label = new QLabel;label->setPixmap(QPixmap(":/trash.png"));TransformWidget w;w.setFront(label);
label = new QLabel;label->setPixmap(QPixmap(":/test.png"));w.setBack(label);
QTimer tm;tm.setInterval(3500);QObject::connect(&tm,&QTimer::timeout,[&]{w.start();});w.show();
tm.start();
return a.exec();}以下为效果图 ,支持自适应罗项目到此下载