#一、简述
今天是新的一年第一篇博客,有大半个月没有更新博客了。我想是时候,打开电脑、拿起键盘、开始在我的代码之路上披荆斩棘,斩杀恶龙。

今天就继续来分享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度时切换窗口,将登陆窗口切换至网络设置窗口。但是在旋转绘制过程中会发现有界面的线条会弯曲,在视觉上会有一点小遗憾,这个问题暂时没有解决,后期如果能够解决将会更新代码。


###完整代码下载
模仿QQ登录窗口(Qt实例)

更新于2017年7月20日

Qt 之 模仿 QQ登陆界面——旋转窗口篇相关推荐

  1. Qt 之 模仿 QQ登陆界面——功能篇(一)

    一.简述 今天是2017年第一篇技术文章,12月末事情太多,一直没来得及更新博客.今天继 Qt 之 模仿 QQ登陆界面--样式篇 这一篇 来简单地看一下对登录界面做的一些功能,主要是登录用户下拉列表和 ...

  2. ios swift模仿qq登陆界面,xml布局

    给大家推荐两个学习的地址: 极客学院的视频:http://www.jikexueyuan.com/path/ios/ 一个博客:http://blog.csdn.net/lizhongfu2013/a ...

  3. Qt之模仿QQ主面板界面

    Qt之模仿QQ主面板界面 Qt之模仿QQ主面板界面 效果图 结尾 效果图 这里大家值得注意的是,QQ等级设置,已经列表展开搜索时的三角符的旋转效果 //QQMainWindow.cpp #includ ...

  4. Qt模仿QQ聊天窗口界面(二)

    Qt模仿QQ聊天窗口界面(二) Qt模仿QQ聊天窗口界面(二) 简述 修改 效果图 后期规划 代码 结尾 简述 在上篇我们已经搭好了QQ聊天窗口的框架,这里在原来的基础上叠加功能,以及优化一些控件. ...

  5. Qt模仿QQ聊天窗口界面(一)

    Qt模仿QQ聊天窗口界面(一) Qt模仿QQ聊天窗口界面(一) 简述 效果图 QQ的聊天窗口 我做的效果图 代码篇 结尾 简述 最近利用业余时间,模仿QQ做了一个聊天窗口界面,功能还不全,准备分几个部 ...

  6. Qt(三)--- 实现QQ登陆界面头像状态栏的功能

    对于QQ登陆界面,可以通过下拉菜单,实现状态的选择,在QQ的头像状态栏需要显示的信息包括:用户的头像以及登陆的状态.这里主要涉及和利用的只是是QMenu以及QAction,同时继承QLabel的类: ...

  7. android模仿qq登录界面,初识Android二之小试牛刀模仿实现qq登陆界面

    初识Android二之小试牛刀模仿实现qq登陆界面.俗话说得好,老师踢开门,修行在自己.勉勉强强学完生命周期,然后悠悠闲闲听了两节课后,老师就布置了一个登陆界面的实现,于是,磕磕绊绊的修行之路开始了. ...

  8. Qt模仿QQ聊天窗口界面(三)

    Qt模仿QQ聊天窗口界面(三)- 截图 Qt模仿QQ聊天窗口界面(三)- 截图 简述 效果图 代码篇 后期规划 结尾 简述 此篇在原来的基础上增加了QQ截图功能.在一个大佬的基础上进行了二次开发. 参 ...

  9. pyqt5登录界面设计——模仿qq登录界面,可登录注册(数据库)

    pyqt5登录界面设计--模仿qq登录界面 一.简单易用的可直接登录的界面--账号密码程序写死 1.1.效果图: 1.2.视频效果图 3.代码说明 4.使用示例 5.全部源码见: 二.带数据库的可登录 ...

最新文章

  1. javascript数组集锦
  2. PathComposePathEffectView 使用
  3. python重现 mysql server has gone away错误以及解决方案
  4. python rpc webservice_PythonXMLRPC服务器端和客户端实例
  5. [VMM 2008虚拟化之初体验-1] 准备环境
  6. Nginx: error while loading shared libraries: libpcre.so.1解决
  7. html改变微信标题栏颜色,带你了解微信在线编辑器的颜色样式修改
  8. 怎么用鼠标选中java中table的某一行_为什么同事的工作效率那么高?学会这些鼠标双击技巧,你也可以的...
  9. 【编辑器】Vim学习笔记
  10. 代码 生成迅雷链接启动迅雷下载
  11. Dos命令 --复制文件(夹)
  12. 【板栗糖GIS】如何给文件夹批量重命名
  13. EasyUI filebox 限制文件上传的类型
  14. 微信抢抢票服务器,2018微信上怎么老是正在抢票?在微信上抢火车票的经验
  15. chrome上字体模糊问题处理
  16. 解决 /usr/bin/ld:cannot find -lxxx 问题
  17. 全免费、保姆级Eclipse32位软件、安装、运行一条龙记录
  18. vivado中设置多核编译
  19. E4G刷Linux,易视宝E4-G 全志A20 刷机 armlinux ubuntu server 教程
  20. 最全Arduino控制电机教程说明和资料分享

热门文章

  1. ZCMU - 1601: 卡斯丁狗去挖矿
  2. kitt2bag 解决“Failed to find match for field intensity”问题
  3. php 表情 代码_PHP 大量QQ表情代码替换
  4. 【软件工程】统计文章字数和出现频率较高词汇的程序实现
  5. ffmpeg输出x264的CBR流或者文件
  6. 重庆锦华计算机学校,重庆市渝北区锦华学校2019年第一季度选聘优秀教师岗位一览表...
  7. 3年收10亿,普陀山悄悄改名重启IPO
  8. java中shutdownoutput_Java Socket shutdownOutput和shutdownInput是否为“Duplicate ACK#:1”
  9. bzoj 3356: [Usaco2004 Jan]禁闭围栏 离散化+树状数组
  10. 2022-2028年全球与中国敞篷汽车座椅行业深度分析