qt 完全實現qq翻轉登入介面
阿新 • • 發佈:2019-02-16
如何用qt實現qq登入介面翻轉效果,這個問題已經糾結我很久了。在一段時間後,再次重新回到這個問題,終於解決了
QTimeLine 是一個線形值定時器
setTransform是一個設定旋轉的函式,函式執行結束直接旋轉到指定位置
第一次做就是沒有注意到這裡,所以沒有解決,這次終於搞定。另外就是根據旋轉方向設定其中一個隱藏,一個顯示以90度為界限,這個大家都懂吧。
QWidget是甚於2維座標的,所以要實現像qq那樣的翻轉效果,必須要能夠繞y軸在3維空間旋轉。看了一些網上教程參考部落格
用到的是QGraphics框架,所以也就用它做了。
注意看的話,上面好像有點bug;不要懷疑,那是因為GIF播放結束,重新播放時的重置效果。程式碼如下
#include <QApplication> #include <QWidget> #include <QLabel> #include <QLineEdit> #include <QPushButton> #include <QHBoxLayout> #include <QVBoxLayout> #include <QGraphicsProxyWidget> #include <QGraphicsView> #include <QGraphicsScene> #include <QTimer> #include <QDebug> #include <QTimeLine> int main(int argc, char *argv[]) { QApplication a(argc, argv); //新建登入窗體控制元件 QWidget *wid1 = new QWidget; QLabel *user = new QLabel(QStringLiteral("使用者名稱:")); QLabel *password = new QLabel(QStringLiteral("密 碼:")); QLineEdit *userEdit = new QLineEdit; userEdit->setPlaceholderText(QStringLiteral("請輸入使用者名稱")); QLineEdit *passwordEdit = new QLineEdit; passwordEdit->setPlaceholderText(QStringLiteral("請輸入密碼")); //輸入窗體佈局 QHBoxLayout *usrHBoxLay = new QHBoxLayout; usrHBoxLay->addWidget(user); usrHBoxLay->addWidget(userEdit); QHBoxLayout *passwordHBoxLay = new QHBoxLayout; passwordHBoxLay->addWidget(password); passwordHBoxLay->addWidget(passwordEdit); QVBoxLayout *vBoxLay1 = new QVBoxLayout; vBoxLay1->addLayout(usrHBoxLay); vBoxLay1->addLayout(passwordHBoxLay); wid1->setLayout(vBoxLay1); //新建設定窗體控制元件 QWidget *wid2 = new QWidget; QLabel *ip = new QLabel(QStringLiteral("IP地址")); QLabel *port = new QLabel(QStringLiteral("埠號")); QLineEdit *ipEdit = new QLineEdit; ipEdit->setPlaceholderText(QStringLiteral("請輸入IP地址")); QLineEdit *portEdit = new QLineEdit; portEdit->setPlaceholderText(QStringLiteral("請輸入埠號")); //設定窗體佈局 QHBoxLayout *ipHBoxLay = new QHBoxLayout; ipHBoxLay->addWidget(ip); ipHBoxLay->addWidget(ipEdit); QHBoxLayout *portHBoxLay = new QHBoxLayout; portHBoxLay->addWidget(port); portHBoxLay->addWidget(portEdit); QVBoxLayout *vBoxLay2 = new QVBoxLayout; vBoxLay2->addLayout(ipHBoxLay); vBoxLay2->addLayout(portHBoxLay); wid2->setLayout(vBoxLay2); //新建View和Scene QGraphicsView *view = new QGraphicsView; QGraphicsScene *scene = new QGraphicsScene; view->setScene(scene); //加入登入和設定窗體 QGraphicsProxyWidget *graphicsWid1 = scene->addWidget(wid1); QGraphicsProxyWidget *graphicsWid2 = scene->addWidget(wid2); //設定窗體旋轉-180度,並隱藏 graphicsWid2->setTransform(QTransform().translate(graphicsWid2->boundingRect().width()/2,graphicsWid2->boundingRect().height()/2) .rotate(-180,Qt::YAxis) .translate(-graphicsWid2->boundingRect().width()/2,-graphicsWid2->boundingRect().height()/2)); graphicsWid2->setVisible(false); //新建線型值鬧鐘 QTimeLine *timeLine = new QTimeLine(1500,scene); timeLine->setStartFrame(0); timeLine->setEndFrame(180); //每次值發生變化,旋轉一定角度 QObject::connect(timeLine,&QTimeLine::frameChanged,[timeLine,graphicsWid1,graphicsWid2](const int frame){ //對於登入窗體正常旋轉 graphicsWid1->setTransform(QTransform().translate(graphicsWid1->boundingRect().width()/2,graphicsWid1->boundingRect().height()/2) .rotate(frame,Qt::YAxis) .translate(-graphicsWid1->boundingRect().width()/2,-graphicsWid1->boundingRect().height()/2)); //對於設定窗體由於開始旋轉到了-180度,所以現在應該是-179,-176,-170....,0,這裡應該是frame-180;也就是加上起點為-180度啦 graphicsWid2->setTransform(QTransform().translate(graphicsWid2->boundingRect().width()/2,graphicsWid2->boundingRect().height()/2) .rotate(frame - 180,Qt::YAxis) .translate(-graphicsWid2->boundingRect().width()/2,-graphicsWid2->boundingRect().height()/2)); switch (timeLine->direction()) { case QTimeLine::Forward: //前面向後面轉,frame從0到180,當frame大於或等於90度時,顯示設定窗體,登入窗體隱藏 if(frame > 90 || frame == 90){ graphicsWid1->setVisible(false); graphicsWid2->setVisible(true); } break; case QTimeLine::Backward: //後面向前面轉,frame從180到0,當frame小於或等於90度時,顯示登入窗體,設定窗體隱藏 if(frame < 90 || frame == 90){ graphicsWid1->setVisible(true); graphicsWid2->setVisible(false); } break; } }); //旋轉結束後,設定線形鬧鐘值的方向 QObject::connect(timeLine,&QTimeLine::finished,[timeLine]{ timeLine->toggleDirection(); }); //啟用鬧鐘,每過一段時間,啟動一次線型鬧鐘 QTimer *timer = new QTimer; timer->setInterval(3000); QObject::connect(timer,&QTimer::timeout,[timeLine]{timeLine->start();}); view->show(); timer->start(); return a.exec(); }
QTimeLine 是一個線形值定時器
它可以附帶一個值的變化,對應的訊號是valueChanged和frameChanged。valueChanged是0-1之間,frameChanged是startFrame()和endFrame()之間,對應值
是從小到大方向,還是從大到小方向;這個取決於direction()屬性值。
setTransform是一個設定旋轉的函式,函式執行結束直接旋轉到指定位置
在QGraphicsScene中的圖元或者QWidget通過QGraphicsScene通過addWidget返回的QGraphicsProxyWidget都可以通過該函式旋轉,並且可以指定旋轉軸。
在開始窗體的角度為0度,初始化後背面的窗體變為-180度;在鬧鐘驅動旋轉時,此時背面窗體要與前面窗體一起旋轉,而且角度應該是-180度到0度,線形鬧鐘反向,然後又是0度到-180度這點很關鍵。而前面的窗體開始是0度,旋轉一次後變180,線型鬧鐘反向,再轉一次又回到0就不需要額外操作。
其它方法
也就是在今晚發麵這篇部落格的同時,我突然搜到了一個解決這個問題的另一種方案,為什麼在今晚寫部落格之前,從未找到過,真草蛋。
方法類似,主要還是我對類還不夠全面的熟悉呀。原來QPainter也有setTransform方法,這樣就可以直接在QWidget的paint函式中直接旋轉了就用不著QGraphics框架了
。同時也謝謝搜到的那篇博主。