国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Qt 之 模仿 QQ登陸界面——旋轉窗口篇

2019-11-08 19:52:41
字體:
來源:轉載
供稿:網友

一、簡述

今天是新的一年第一篇博客,有大半個月沒有更新博客了。我想是時候,打開電腦、拿起鍵盤、開始在我的代碼之路上披荊斬棘,斬殺惡龍。

今天就繼續來分享QQ登錄界面的那些事。QQ登錄界面的標題欄有一個小三角的按鈕,一般情況下,大家可能并不會點擊這個按鈕,因為正常情況下大家登錄QQ都不需要進行網絡設置,只有在網絡有限制的情況下,我們需要設置一些代理來登錄QQ。

當我們點擊這個小三角按鈕,我們會發現QQ的有一個旋轉動畫從登錄界面跳轉到網絡設置界面。仔細看其實會發現登錄界面和網絡設置界面不是同一個窗口,而且兩個界面的寬高各不相等,也就是差不多在旋轉到90度時切換了窗口。

那么是不是可以用Qt實現類似的效果呢?萬能的Qt告訴你,當然可以。下面就來看一看如何實現。


QQ登錄界面點擊小三角旋轉到網絡設置界面:

這里寫圖片描述


我的效果

這里寫圖片描述


二、代碼之路

rotatewidget.h

#ifndef ROTATEWIDGET_H#define ROTATEWIDGET_H#include <QStackedWidget>class LoginWindow;class LoginNetSetWindow;class RotateWidget : public QStackedWidget{ Q_OBJECTpublic: RotateWidget(QWidget *parent = NULL); ~RotateWidget();PRivate: // 初始化旋轉的窗口; void initRotateWindow(); // 繪制旋轉效果; void paintEvent(QPaintEvent* event);private slots: // 開始旋轉窗口; void onRotateWindow(); // 窗口旋轉結束; void onRotateFinished();private: // 當前窗口是否正在旋轉; bool m_isRoratingWindow; // 登錄界面; LoginWindow* m_loginWindow; // 網絡設置界面; LoginNetSetWindow* m_loginNetSetWindow; int m_nextPageIndex;};#endif // ROTATEWIDGET_H

rotatewidget.cpp

#include "rotatewidget.h"#include <QPropertyAnimation>#include "loginwindow.h"#include "loginnetsetwindow.h"RotateWidget::RotateWidget(QWidget *parent) : QStackedWidget(parent) , m_isRoratingWindow(false) , m_nextPageIndex(0){ this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint| Qt::WindowMinimizeButtonHint); this->setAttribute(Qt::WA_TranslucentBackground); // 給窗口設置rotateValue屬性; this->setProperty("rotateValue", 0); initRotateWindow();}RotateWidget::~RotateWidget(){}// 初始化旋轉的窗口;void RotateWidget::initRotateWindow(){ m_loginWindow = new LoginWindow(this); // 這里定義了兩個信號,需要自己去發送信號; connect(m_loginWindow, SIGNAL(rotateWindow()), this, SLOT(onRotateWindow())); connect(m_loginWindow, SIGNAL(closeWindow()), this, SLOT(close())); m_loginNetSetWindow = new LoginNetSetWindow(this); connect(m_loginNetSetWindow, SIGNAL(rotateWindow()), this, SLOT(onRotateWindow())); connect(m_loginNetSetWindow, SIGNAL(closeWindow()), this, SLOT(close())); this->addWidget(m_loginWindow); this->addWidget(m_loginNetSetWindow); // 這里寬和高都增加,是因為在旋轉過程中窗口寬和高都會變化; this->setFixedSize(QSize(m_loginWindow->width() + 20, m_loginWindow->height() + 100));}// 開始旋轉窗口;void RotateWidget::onRotateWindow(){ // 如果窗口正在旋轉,直接返回; if (m_isRoratingWindow) { return; } m_isRoratingWindow = true; m_nextPageIndex = (currentIndex() + 1) >= count() ? 0 : (currentIndex() + 1); QPropertyAnimation *rotateAnimation = new QPropertyAnimation(this, "rotateValue"); // 設置旋轉持續時間; rotateAnimation->setDuration(600); // 設置旋轉角度變化趨勢; rotateAnimation->setEasingCurve(QEasingCurve::InCubic); // 設置旋轉角度范圍; rotateAnimation->setStartValue(0); rotateAnimation->setEndValue(180); connect(rotateAnimation, SIGNAL(valueChanged(QVariant)), this, SLOT(repaint())); connect(rotateAnimation, SIGNAL(finished()), this, SLOT(onRotateFinished())); // 隱藏當前窗口,通過不同角度的繪制來達到旋轉的效果; currentWidget()->hide(); rotateAnimation->start();}// 旋轉結束;void RotateWidget::onRotateFinished(){ m_isRoratingWindow = false; setCurrentWidget(widget(m_nextPageIndex)); repaint();}// 繪制旋轉效果;void RotateWidget::paintEvent(QPaintEvent* event){ if (m_isRoratingWindow) { // 小于90度時; int rotateValue = this->property("rotateValue").toInt(); if (rotateValue <= 90) { QPixmap rotatePixmap(currentWidget()->size()); currentWidget()->render(&rotatePixmap); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QTransform transform; transform.translate(width() / 2, 0); transform.rotate(rotateValue, Qt::YAxis); painter.setTransform(transform); painter.drawPixmap(-1 * width() / 2, 0, rotatePixmap); } // 大于90度時 else { QPixmap rotatePixmap(widget(m_nextPageIndex)->size()); widget(m_nextPageIndex)->render(&rotatePixmap); QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QTransform transform; transform.translate(width() / 2, 0); transform.rotate(rotateValue + 180, Qt::YAxis); painter.setTransform(transform); painter.drawPixmap(-1 * width() / 2, 0, rotatePixmap); } } else { return __super::paintEvent(event); }}

在LoginWindow和LoginNetSetWindow中實現鼠標拖拽窗口移動。

本窗口不需要移動,只需通知父窗口移動即可

void LoginNetSetWindow::mousePressEvent(QMouseEvent *event){ if (event->button() == Qt::LeftButton) { m_isPressed = true; m_startMovePos = event->globalPos(); } return QWidget::mousePressEvent(event);}void LoginNetSetWindow::mouseMoveEvent(QMouseEvent *event){ if (m_isPressed) { QPoint movePoint = event->globalPos() - m_startMovePos; QPoint widgetPos = this->parentWidget()->pos() + movePoint; m_startMovePos = event->globalPos(); this->parentWidget()->move(widgetPos.x(), widgetPos.y()); } return QWidget::mouseMoveEvent(event);}void LoginNetSetWindow::mouseReleaseEvent(QMouseEvent *event){ m_isPressed = false; return QWidget::mouseReleaseEvent(event);}// 在子窗口關閉時通知關閉父窗口;void LoginNetSetWindow::closeEvent(QCloseEvent *event){ emit closeWindow(); return __super::closeEvent(event);}

注意:

在設置窗口寬高時添加了如下代碼,至于為什么?請看下面圖片效果。

// 這里寬和高都增加,是因為在旋轉過程中窗口寬和高都會變化;this->setFixedSize(QSize(m_loginWindow->width() + 20, m_loginWindow->height() + 100));

這里寫圖片描述

我們知道使用QQ截圖,在鼠標移動到某個窗口上時,QQ會自動將當前截圖區域設置為這個窗口的大小,我們看到用QQ進行截圖時,將鼠標放在QQ登錄界面上選取的區域要大于實際的界面,所以QQ的登錄界面并不是一個單獨的窗口,而是后面那個透明窗口的子窗口,其實也就類似于我們將登錄界面放在一個Widget 上,然后將這個Widget背景置為透明,至于為什么要加大寬高,是因為在旋轉的過程中窗口的寬高發生了變化,然后不加大寬高,窗口將會被遮擋。

加長寬高用QQ截圖顯示效果:

這里寫圖片描述

不加長寬高的下方被遮擋:

這里寫圖片描述

我們發現窗口下方會被遮擋,這就是為什么要加長寬高了。至于為什么QQ窗口四周都會有多余空間,而我這里只有右方和下方是因為旋轉效果不一樣所以設置的不一樣罷了。


通過QPropertyAnimation類來改變旋轉角度值,在paintEvent不斷繪制不同角度下的窗口來達到旋轉的效果。在旋轉到90度時切換窗口,將登陸窗口切換至網絡設置窗口。但是在旋轉繪制過程中會發現有界面的線條會彎曲,在視覺上會有一點小遺憾,這個問題暫時沒有解決,后期如果能夠解決將會更新代碼。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 泗水县| 濮阳县| 米林县| 庄浪县| 竹溪县| 克什克腾旗| 汶上县| 白水县| 水富县| 大连市| 于都县| 绵阳市| 灵台县| 高州市| 玛曲县| 罗定市| 响水县| 大渡口区| 含山县| 石狮市| 玉树县| 银川市| 宁陕县| 深圳市| 安塞县| 建瓯市| 琼海市| 甘南县| 清新县| 梧州市| 吉安市| 屯留县| 邻水| 松阳县| 武宁县| 嘉峪关市| 霍林郭勒市| 视频| 抚顺县| 伊金霍洛旗| 遵化市|