继续上一章的360新特性界面。源代码:http://download.csdn.net/detail/zhangyang1990828/5241242

上一章中实现了整个界面的纯UI设计,这次我们让它生动起来。

QT学习(五)

首先让“360安全桌面”“木马防火墙”..这四个按钮“动”起来。

让这个按钮有几种状态:

①鼠标进入时变成低亮高透明

②鼠标离开时恢复原状

③鼠标点击后变成高亮低透明

为了实现这几种状态,需要三个事件和两个变量:

enterEvent(QEvent* e);

leaveEvent(QEvent* e);

mousePressEvent(QMouseEvent* e);

m_mousePressFlag;

m_mouseEnterFlag;

通过这三个事件和两个变量,就可以实现按钮的几种状态了。(还需要通过信号槽来实现只有一个按钮被选中)

代码:

  1. connect(label, SIGNAL(signalLabelPress(CLabel*)), this, SLOT(slotLabelButtonPress(CLabel*)));
  1. void DataBrain::slotLabelButtonPress(CLabel *label)
  2. {
  3. for (int i = 0; i < WINDOW_BUTTON_COUNT; i++)
  4. {
  5. if (label != m_pLabelBtnArray[i])
  6. {
  7. m_pLabelBtnArray[i]->setMousePressFlag(false);
  8. }
  9. }
  10. }
  1. //按钮特效
  2. void CLabel::setMouseEnterFlag(bool flag)
  3. {
  4. m_mouseEnterFlag=flag;
  5. this->update();
  6. }
  7. void CLabel::setMousePressFlag(bool flag)
  8. {
  9. m_mousePressFlag=flag;
  10. this->update();
  11. }
  12. bool CLabel::getMouseEnterFlag()
  13. {
  14. return m_mouseEnterFlag;
  15. }
  16. bool CLabel::getMousePressFlag()
  17. {
  18. return m_mousePressFlag;
  19. }
  20. void CLabel::enterEvent(QEvent *e)
  21. {
  22. if(!getMousePressFlag())
  23. {
  24. setMouseEnterFlag(true);
  25. }
  26. this->setCursor(Qt::PointingHandCursor);//设置鼠标的形状
  27. }
  28. void CLabel::leaveEvent(QEvent *e)
  29. {
  30. setMouseEnterFlag(false);
  31. }
  32. void CLabel::mousePressEvent(QMouseEvent *e)
  33. {
  34. if(e->button()==Qt::LeftButton)
  35. {
  36. setMousePressFlag(true);
  37. emit signalLabelPress(this);
  38. }
  39. }

效果图:

ok!我们继续来实现右上角关闭按钮的动态的效果。

和上面的相同,关闭的按钮也是需要三个状态:

①鼠标进入时

②鼠标离开时

③鼠标点击后

不同的是,关闭按钮不是对按钮设置样式,而是对它进行更换图片。

这里值得一提的是,这里用的eventFilter(事件过滤器),对某个控件install一个eventFiler后,可以在eventFilter的事件中通过传递进来的两个参数(QObject*,QEvent*)来对事件进行控制。

十分简单,上代码:

  1. //关闭按钮的效果
  2. void DataBrain::createEventFilter()
  3. {
  4. m_pCloseBtn->installEventFilter(this);
  5. }
  6. bool DataBrain::eventFilter(QObject *target , QEvent *event)
  7. {
  8. EButtonMouseState state=EButtonMouseNone;
  9. if(target==m_pCloseBtn)
  10. {
  11. if(event->type()==QEvent::Enter)
  12. {
  13. state=EButtonMouseEnter;
  14. }
  15. else if(event->type()==QEvent::Leave)
  16. {
  17. state=EButtonMouseDefault;
  18. }
  19. else if(((QMouseEvent*)event)->button()==Qt::LeftButton)
  20. {
  21. if(event->type()==QEvent::MouseButtonPress)
  22. {
  23. state=EButtonMousePress;
  24. }
  25. else if (event->type()==QEvent::MouseButtonRelease)
  26. {
  27. state = EButtonMouseEnter;
  28. }
  29. }
  30. if(state!=EButtonMouseNone)
  31. {
  32. setButtonIcon((QToolButton*)target,state);
  33. }
  34. }
  35. return QWidget::eventFilter(target, event);
  36. }
  37. void DataBrain::setButtonIcon(QToolButton *btn, EButtonMouseState state)
  38. {
  39. QPixmap pixmap(":/images/images/btn_close.png");
  40. int nWidth = pixmap.width()/4;
  41. int nHeight = pixmap.height();
  42. btn->setIcon(QIcon(pixmap.copy(QRect(state*nWidth, 0, nWidth, nHeight))));
  43. btn->setIconSize(QSize(nWidth, nHeight));
  44. }
  1. connect(m_pCloseBtn,SIGNAL(clicked()),qApp,SLOT(quit()));//给按钮加上关闭程序的功能

效果图:


最后来实现窗口的推拽功能(点击串口上的一部分内可以拖动窗口)和主页面选择页的拖拽(页面选择以及按钮选择的变换)

这里是整个设计中最复杂的地方!

首先需要先确定要完成窗口拖拽和主页面选择需要抽象出几个方法,怎样划分这些方法

①鼠标被按下事件mousePressEvent,在这里需要去判断鼠标的左键和右键,左键的话按下的区域是在窗口拖拽区还是在主页选择区,这里需要注意的是,关闭按钮也在窗口拖拽区,需要在关闭按钮的的点击事件将窗口拖拽的flag设置成false。完成这个类需要m_mouseMoveWindowFlag(窗口是否能被拖拽的flag),m_mousePressFlag(主窗口能否被拖拽的flag)两个flag;右键的话判断当前的主页面是否能向左滚动,需要setLabelMove和getLabelMove进行设置和读取m_labelMoveFlag来对主页面能被向左移还是向右移进行flag。m_labelMoveFlag=flase能向右移不能向左移,m_labelMoveFlag=true能向左移不能向右移。(这里的左移和右移指的是整页的移动)

②鼠标移动的事件mouseMoveEvent,在这里需要进行判断m_mouseMoveWindowFlag和m_mousePressFlag,通过这两个标识去完成是进行窗口的移动还是主页面的拖拽。(这里需要注意的是,这里的移动是拖拽,需要进行不断的事件响应,才能出现拖拽的效果。)

③鼠标的按键释放事件mouseReleaseEvent,在这里需要对m_mouseMoveWindowFlag和m_mousePressFlag进行判断,看刚结束的鼠标按键按下和释放过程中做了什么,如果m_mousePressFlag=true,则干才进行了主页面的拖拽,需要通过鼠标按键按下时鼠标的坐标和释放时鼠标的坐标来进行判断鼠标拖拽的方向,再通过moveCurrentPage(整页移动的函数)来完成页面的滚动;如果m_mousePressFlag=false,则刚才进行了窗口移动事件,需要在这里重新将m_mouseMoveWindowFlag设置成false。

③整页移动的函数moveCurrentPage,通过起始点的坐标和终点的坐标来判断滚动的方向。如果没有鼠标的拖动,而是通过鼠标右键或者快捷键来实现的页面滚动,则直接进行页面滚动。

④拖拽主页面到新的页面时,需要用改变当前选择按钮的函数changeCurrentButton,需要在这里调用CButton的setMousePressFlag函数重新对选中按钮进行设定。

⑤slotChangeCurrentPage函数,需要对点击按钮的事件进行响应,点击按钮则主页面进行响应的滚动

⑥快捷键的响应keyPressEvent,这里对快捷键进行设置。

OK!明白了以上的就可以了,代码:

  1. //窗口拖拽
  2. void DataBrain::mousePressEvent(QMouseEvent *e)
  3. {
  4. if(e->button()==Qt::LeftButton)
  5. {
  6. m_mouseSrcPos=e->pos();
  7. if(m_mouseSrcPos.y()<=40)
  8. {
  9. m_mouseMoveWindowFlag=true;
  10. }
  11. else
  12. {
  13. m_currentFgXpos=m_pLabelFg->x();
  14. m_mousePressFlag=true;
  15. }
  16. }
  17. //右键左移
  18. else if(e->button()==Qt::RightButton)
  19. {
  20. if(getLabelMove())
  21. {
  22. if(m_currentFgIndex>0)
  23. {
  24. m_currentFgIndex--;
  25. moveCurrentPage(false);
  26. }
  27. }
  28. }
  29. }
  30. inline void DataBrain::setLabelMove(bool enable)
  31. {
  32. m_labelMoveFlag = enable;
  33. }
  34. inline bool DataBrain::getLabelMove()
  35. {
  36. return m_labelMoveFlag;
  37. }
  38. void DataBrain::moveCurrentPage(bool direction)
  39. {
  40. int currentXpos = 0;//当前label的x坐标
  41. int destXpos = 0;//目标x坐标
  42. //改变当前页面对应的按钮
  43. changeCurrentButton();
  44. //图片的几个分割点
  45. //0-680, 680-1360, 1360-2040, 2040-2720
  46. //真:向左移;  假:向右移
  47. if (direction)
  48. {
  49. //左移的几种可能性,对于x坐标
  50. //index=0, 将label移动到-680*0
  51. //index=1, 将label移动到-680*1
  52. //index=2, 将label移动到-680*2
  53. //index=3, 将label移动到-680*3
  54. setLabelMove(false);
  55. currentXpos = m_pLabelFg->x();
  56. destXpos = -WINDOW_WIDTH * m_currentFgIndex;
  57. while(currentXpos > destXpos)//平滑滚动效果
  58. {
  59. m_pLabelFg->move(currentXpos-WINDOW_PAGE_MOVE, WINDOW_START_Y);
  60. currentXpos = m_pLabelFg->x();
  61. qApp->processEvents(QEventLoop::AllEvents);//依然保持监听事件
  62. }
  63. m_pLabelFg->move(destXpos, WINDOW_START_Y);//确保最后移到指定的位置
  64. setLabelMove(true);
  65. }
  66. else
  67. {
  68. //右移的几种可能性,对于x坐标,与左移一致
  69. //index=0, 将label移动到-680*0
  70. //index=1, 将label移动到-680*1
  71. //index=2, 将label移动到-680*2
  72. //index=3, 将label移动到-680*3
  73. setLabelMove(false);
  74. currentXpos = m_pLabelFg->x();
  75. destXpos = -WINDOW_WIDTH * m_currentFgIndex;
  76. while(currentXpos < destXpos)
  77. {
  78. m_pLabelFg->move(currentXpos+WINDOW_PAGE_MOVE, WINDOW_START_Y);
  79. currentXpos = m_pLabelFg->x();
  80. qApp->processEvents(QEventLoop::AllEvents);
  81. }
  82. m_pLabelFg->move(destXpos, WINDOW_START_Y);
  83. setLabelMove(true);
  84. }
  85. }
  86. void DataBrain::changeCurrentButton()
  87. {
  88. for (int i = 0; i < WINDOW_BUTTON_COUNT; i++)
  89. {
  90. if (i != m_currentFgIndex)
  91. {
  92. m_pLabelBtnArray[i]->setMousePressFlag(false);
  93. }
  94. else
  95. {
  96. m_pLabelBtnArray[i]->setMousePressFlag(true);
  97. }
  98. }
  99. }
  100. void DataBrain::slotChangeCurrentPage(CLabel *label)
  101. {
  102. int index = 0;
  103. for (int i = 0; i < WINDOW_PAGE_COUNT; i++)
  104. {
  105. if (label == m_pLabelBtnArray[i])
  106. {
  107. index = i;
  108. break;
  109. }
  110. }
  111. //移动的几种可能性,对于x坐标
  112. //index=0, 将label移动到-680*0
  113. //index=1, 将label移动到-680*1
  114. //index=2, 将label移动到-680*2
  115. //index=3, 将label移动到-680*3
  116. //点击左边的按钮 右移
  117. if (index < m_currentFgIndex)
  118. {
  119. while(index != m_currentFgIndex)
  120. {
  121. m_currentFgIndex--;
  122. moveCurrentPage(false);
  123. }
  124. }
  125. else if (index > m_currentFgIndex) //点击右边的按钮 左移
  126. {
  127. while(index != m_currentFgIndex)
  128. {
  129. m_currentFgIndex++;
  130. moveCurrentPage(true);
  131. }
  132. }
  133. }
  134. void DataBrain::mouseMoveEvent(QMouseEvent *e)
  135. {
  136. int x = 0;
  137. if (m_mousePressFlag)
  138. {
  139. if (getLabelMove())
  140. {
  141. m_mouseDstPos = e->pos();
  142. x = m_mouseDstPos.x() - m_mouseSrcPos.x();
  143. setLabelMove(false);
  144. m_pLabelFg->move(m_currentFgXpos + x, WINDOW_START_Y);
  145. setLabelMove(true);
  146. }
  147. }
  148. else if (m_mouseMoveWindowFlag)
  149. {
  150. m_mouseDstPos = e->pos();
  151. this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos);
  152. }
  153. }
  154. void DataBrain::mouseReleaseEvent(QMouseEvent *e)
  155. {
  156. int xpos = 0;
  157. if (m_mousePressFlag)
  158. {
  159. if (getLabelMove())
  160. {
  161. m_mouseDstPos = e->pos();
  162. xpos = m_mouseDstPos.x() - m_mouseSrcPos.x();
  163. if (xpos > 0)//右移
  164. {
  165. if (xpos >= WINDOW_ONEBUTTON_WIDTH)
  166. {
  167. if (m_currentFgIndex > 0)
  168. {
  169. m_currentFgIndex--;
  170. moveCurrentPage(false); //右移
  171. }
  172. else
  173. {
  174. moveCurrentPage(true); //左移
  175. }
  176. }
  177. else
  178. {
  179. moveCurrentPage(true); //左移
  180. }
  181. }
  182. else //左移
  183. {
  184. if (xpos <= -WINDOW_ONEBUTTON_WIDTH)
  185. {
  186. if (m_currentFgIndex < WINDOW_PAGE_COUNT-1)
  187. {
  188. m_currentFgIndex++;
  189. moveCurrentPage(true); //左移
  190. }
  191. else
  192. {
  193. moveCurrentPage(false); //右移
  194. }
  195. }
  196. else
  197. {
  198. moveCurrentPage(false); //右移
  199. }
  200. }
  201. m_mousePressFlag = false;
  202. }
  203. }
  204. else if (m_mouseMoveWindowFlag)
  205. {
  206. m_mouseMoveWindowFlag = false;
  207. }
  208. }
  209. //快捷键
  210. void DataBrain::keyPressEvent(QKeyEvent *e)
  211. {
  212. if (getLabelMove())
  213. {
  214. switch(e->key())
  215. {
  216. case Qt::Key_Left:
  217. case Qt::Key_Up:
  218. if (m_currentFgIndex > 0)
  219. {
  220. m_currentFgIndex--;
  221. moveCurrentPage(false); //右移
  222. }
  223. break;
  224. case Qt::Key_Right:
  225. case Qt::Key_Down:
  226. if (m_currentFgIndex < WINDOW_PAGE_COUNT-1)
  227. {
  228. m_currentFgIndex++;
  229. moveCurrentPage(true); //左移
  230. }
  231. break;
  232. default:
  233. break;
  234. }
  235. }
  236. }

代码有点长,需要全部代码的可以去 http://download.csdn.net/detail/zhangyang1990828/5241242下载源代码。效果图就不上了,和360的新特性差不多。

通过这样一个例子,我想对于整个Qt的机制有了一定的了解吧,以后有好例子还会与大家分享的。

QT学习(五)----360界面制作(2终结)的更多相关文章

  1. qt学习 (五) 登陆界面之连接按钮

    登陆步骤是比对输入的账号密码与数据库中的表项目是否一致 一样,  跳出mainwidget对话框 不一样,跳出消息错误框 今天就是要进去, 因为进去以后是widget的窗口,所以把用来核对消息的数据库 ...

  2. QT学习(四)----360界面制作(1)

    参照网上的资料,模仿了一份360新特效的界面. 源代码在:http://download.csdn.net/detail/zhangyang1990828/5238013 360真实效果:(最好自己打 ...

  3. JFinal Web开发学习(五)注册界面和后端验证

    效果: 直接点击注册后 : 后端验证是可靠地,前端js验证是不可靠的.只需要在浏览器删除js验证代码即可突破js验证. 1.注册界面 在WebRoot下新建regist.jsp <%@ page ...

  4. Qt之实现360安全卫士主界面代码开源

    匆匆一年又过去了,总结去年一年的节奏就是忙爆了:生活忙.工作忙,值得庆幸的是没有瞎忙:今天打开博客园查看我的博客,才发现几乎差不多一年时间没写博客了:博客文章就是记忆,就是曾经努力过的见证,感谢博客园 ...

  5. 第15.10节 PyQt(Python+Qt)入门学习:Qt Designer可视化设计界面组件与QWidget类相关的组件属性详解

    PyQt学习有阵子了,对章节的骨架基本考虑好了,准备本节就写组件的属性的,结果一是日常工作繁忙,经常晚上还要加班,二是Qt的组件属性很多,只能逐一学习.研究和整理,花的时间有点长,不过终于将可视化设计 ...

  6. qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果

    应大家的要求,还是把完整的project文件贴出来,大家省点事:http://www.kuaipan.cn/file/id_48923272389086450.htm 先看看执行效果,我用的群创7寸屏 ...

  7. QT学习之windows下安装配置PyQt5

    windows下安装配置PyQt5 目录 为什么要学习QT 命令行安装PyQt5以及PyQt5-tools 配置QtDesigner.PyUIC及PyRcc 为什么要学习QT python下与界面开发 ...

  8. QT学习2

    一.常用控件与常用的功能函数.  QDialog.QMainWindow.QPushButton.QLabel.QLineEdit 构造函数指定父容器.setText,getText,size,res ...

  9. Qt 学习之路 2(51):布尔表达式树模型

    Qt 学习之路 2(51):布尔表达式树模型 豆子 2013年5月15日 Qt 学习之路 2 17条评论 本章将会是自定义模型的最后一部分.原本打算结束这部分内容,不过实在不忍心放弃这个示例.来自于 ...

随机推荐

  1. UiPath直播课程

    UiPath实现拉勾招聘信息的抓取和汇总 https://www.bilibili.com/video/av81859882 UiPath企业框架Reframework的介绍和使用 https://w ...

  2. .NET混合开发解决方案24 WebView2对比CefSharp的超强优势

    系列目录     [已更新最新开发文章,点击查看详细] WebView2控件应用详解系列博客 .NET桌面程序集成Web网页开发的十种解决方案 .NET混合开发解决方案1 WebView2简介 .NE ...

  3. SpringBoot 整合文件上传 elment Ui 上传组件

    SpringBoot 整合文件上传 elment Ui 上传组件 本文章记录 自己学习使用 侵权必删! 前端代码 博主最近在学 elment Ui 所以 前端使用 elmentUi 的 upload ...

  4. 在Visual Studio Code 中配置Python 中文乱码问题

    在Visual Studio Code 中配置Python 中文乱码问题 方法一:直接代码修改字符集 添加前四行代码 import io import sys #改变标准输出的默认编码 sys.std ...

  5. Linux 目录挂载服务

    Linux 服务器挂载文件目录通常有三种形式,手动挂载.自动挂载.Autofs 自动挂载,下面对这三个挂载做一下介绍,接受一下这三个区别以及使用场景: 准备服务器和客户端: server 192.16 ...

  6. 基于UniApp社区论坛多端开发实战

    什么是移动端WebApp 移动端WebApp: 泛指手持设备移动端的web 特点: - 类App 应用,运行环境是浏览器 - 可以包一层壳,成为App - 常见的混合应用: ionic, Cordov ...

  7. 集合容器和Hash表

    集合容器 集合相当于一个容器,在我们使用Arraylist的时候添加参数相当与放了一个容器中.这里面的元素是可以重复的 在HashSet中添加元素是没有重复的,我们来写一个测试看一下 public s ...

  8. 零基础学Java(6)控制流程

    控制流程 与任何程序设计语言一样,Java使用条件语句和循环结构确定控制流程. 块作用域 我们首先要了解块(block)的概念. 块是指由若干条Java语句组成的语句,并用一对大括号括起来.块确定了变 ...

  9. Solution -「SDOI2011」拦截导弹

    Sol.   题目要求一个数对序列的二维最长下降子序列,我们称其为 Q.并求出每一个元素分别在可能的 Q 中出现了多少次.   直接 Dp,时间复杂度 \(O(n^2)\) 不行.考虑 CDQ 分治 ...

  10. Ubu18远程登录密匙设置

    Ubu18设置远程密匙登录 相关文件 /etc/ssh/sshd_config 注意vscode使用博客园插件需要进行端口转发,在vscode端口处设置41385 本地生成密匙,任选一种,这里只介绍第 ...