QT学习(五)----360界面制作(2终结)
继续上一章的360新特性界面。源代码:http://download.csdn.net/detail/zhangyang1990828/5241242
上一章中实现了整个界面的纯UI设计,这次我们让它生动起来。
QT学习(五)
首先让“360安全桌面”“木马防火墙”..这四个按钮“动”起来。
让这个按钮有几种状态:
①鼠标进入时变成低亮高透明
②鼠标离开时恢复原状
③鼠标点击后变成高亮低透明
为了实现这几种状态,需要三个事件和两个变量:
enterEvent(QEvent* e);
leaveEvent(QEvent* e);
mousePressEvent(QMouseEvent* e);
m_mousePressFlag;
m_mouseEnterFlag;
通过这三个事件和两个变量,就可以实现按钮的几种状态了。(还需要通过信号槽来实现只有一个按钮被选中)
代码:
- connect(label, SIGNAL(signalLabelPress(CLabel*)), this, SLOT(slotLabelButtonPress(CLabel*)));
- void DataBrain::slotLabelButtonPress(CLabel *label)
- {
- for (int i = 0; i < WINDOW_BUTTON_COUNT; i++)
- {
- if (label != m_pLabelBtnArray[i])
- {
- m_pLabelBtnArray[i]->setMousePressFlag(false);
- }
- }
- }
- //按钮特效
- void CLabel::setMouseEnterFlag(bool flag)
- {
- m_mouseEnterFlag=flag;
- this->update();
- }
- void CLabel::setMousePressFlag(bool flag)
- {
- m_mousePressFlag=flag;
- this->update();
- }
- bool CLabel::getMouseEnterFlag()
- {
- return m_mouseEnterFlag;
- }
- bool CLabel::getMousePressFlag()
- {
- return m_mousePressFlag;
- }
- void CLabel::enterEvent(QEvent *e)
- {
- if(!getMousePressFlag())
- {
- setMouseEnterFlag(true);
- }
- this->setCursor(Qt::PointingHandCursor);//设置鼠标的形状
- }
- void CLabel::leaveEvent(QEvent *e)
- {
- setMouseEnterFlag(false);
- }
- void CLabel::mousePressEvent(QMouseEvent *e)
- {
- if(e->button()==Qt::LeftButton)
- {
- setMousePressFlag(true);
- emit signalLabelPress(this);
- }
- }
效果图:

ok!我们继续来实现右上角关闭按钮的动态的效果。
和上面的相同,关闭的按钮也是需要三个状态:
①鼠标进入时
②鼠标离开时
③鼠标点击后
不同的是,关闭按钮不是对按钮设置样式,而是对它进行更换图片。
这里值得一提的是,这里用的eventFilter(事件过滤器),对某个控件install一个eventFiler后,可以在eventFilter的事件中通过传递进来的两个参数(QObject*,QEvent*)来对事件进行控制。
十分简单,上代码:
- //关闭按钮的效果
- void DataBrain::createEventFilter()
- {
- m_pCloseBtn->installEventFilter(this);
- }
- bool DataBrain::eventFilter(QObject *target , QEvent *event)
- {
- EButtonMouseState state=EButtonMouseNone;
- if(target==m_pCloseBtn)
- {
- if(event->type()==QEvent::Enter)
- {
- state=EButtonMouseEnter;
- }
- else if(event->type()==QEvent::Leave)
- {
- state=EButtonMouseDefault;
- }
- else if(((QMouseEvent*)event)->button()==Qt::LeftButton)
- {
- if(event->type()==QEvent::MouseButtonPress)
- {
- state=EButtonMousePress;
- }
- else if (event->type()==QEvent::MouseButtonRelease)
- {
- state = EButtonMouseEnter;
- }
- }
- if(state!=EButtonMouseNone)
- {
- setButtonIcon((QToolButton*)target,state);
- }
- }
- return QWidget::eventFilter(target, event);
- }
- void DataBrain::setButtonIcon(QToolButton *btn, EButtonMouseState state)
- {
- QPixmap pixmap(":/images/images/btn_close.png");
- int nWidth = pixmap.width()/4;
- int nHeight = pixmap.height();
- btn->setIcon(QIcon(pixmap.copy(QRect(state*nWidth, 0, nWidth, nHeight))));
- btn->setIconSize(QSize(nWidth, nHeight));
- }
- 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!明白了以上的就可以了,代码:
- //窗口拖拽
- void DataBrain::mousePressEvent(QMouseEvent *e)
- {
- if(e->button()==Qt::LeftButton)
- {
- m_mouseSrcPos=e->pos();
- if(m_mouseSrcPos.y()<=40)
- {
- m_mouseMoveWindowFlag=true;
- }
- else
- {
- m_currentFgXpos=m_pLabelFg->x();
- m_mousePressFlag=true;
- }
- }
- //右键左移
- else if(e->button()==Qt::RightButton)
- {
- if(getLabelMove())
- {
- if(m_currentFgIndex>0)
- {
- m_currentFgIndex--;
- moveCurrentPage(false);
- }
- }
- }
- }
- inline void DataBrain::setLabelMove(bool enable)
- {
- m_labelMoveFlag = enable;
- }
- inline bool DataBrain::getLabelMove()
- {
- return m_labelMoveFlag;
- }
- void DataBrain::moveCurrentPage(bool direction)
- {
- int currentXpos = 0;//当前label的x坐标
- int destXpos = 0;//目标x坐标
- //改变当前页面对应的按钮
- changeCurrentButton();
- //图片的几个分割点
- //0-680, 680-1360, 1360-2040, 2040-2720
- //真:向左移; 假:向右移
- if (direction)
- {
- //左移的几种可能性,对于x坐标
- //index=0, 将label移动到-680*0
- //index=1, 将label移动到-680*1
- //index=2, 将label移动到-680*2
- //index=3, 将label移动到-680*3
- setLabelMove(false);
- currentXpos = m_pLabelFg->x();
- destXpos = -WINDOW_WIDTH * m_currentFgIndex;
- while(currentXpos > destXpos)//平滑滚动效果
- {
- m_pLabelFg->move(currentXpos-WINDOW_PAGE_MOVE, WINDOW_START_Y);
- currentXpos = m_pLabelFg->x();
- qApp->processEvents(QEventLoop::AllEvents);//依然保持监听事件
- }
- m_pLabelFg->move(destXpos, WINDOW_START_Y);//确保最后移到指定的位置
- setLabelMove(true);
- }
- else
- {
- //右移的几种可能性,对于x坐标,与左移一致
- //index=0, 将label移动到-680*0
- //index=1, 将label移动到-680*1
- //index=2, 将label移动到-680*2
- //index=3, 将label移动到-680*3
- setLabelMove(false);
- currentXpos = m_pLabelFg->x();
- destXpos = -WINDOW_WIDTH * m_currentFgIndex;
- while(currentXpos < destXpos)
- {
- m_pLabelFg->move(currentXpos+WINDOW_PAGE_MOVE, WINDOW_START_Y);
- currentXpos = m_pLabelFg->x();
- qApp->processEvents(QEventLoop::AllEvents);
- }
- m_pLabelFg->move(destXpos, WINDOW_START_Y);
- setLabelMove(true);
- }
- }
- void DataBrain::changeCurrentButton()
- {
- for (int i = 0; i < WINDOW_BUTTON_COUNT; i++)
- {
- if (i != m_currentFgIndex)
- {
- m_pLabelBtnArray[i]->setMousePressFlag(false);
- }
- else
- {
- m_pLabelBtnArray[i]->setMousePressFlag(true);
- }
- }
- }
- void DataBrain::slotChangeCurrentPage(CLabel *label)
- {
- int index = 0;
- for (int i = 0; i < WINDOW_PAGE_COUNT; i++)
- {
- if (label == m_pLabelBtnArray[i])
- {
- index = i;
- break;
- }
- }
- //移动的几种可能性,对于x坐标
- //index=0, 将label移动到-680*0
- //index=1, 将label移动到-680*1
- //index=2, 将label移动到-680*2
- //index=3, 将label移动到-680*3
- //点击左边的按钮 右移
- if (index < m_currentFgIndex)
- {
- while(index != m_currentFgIndex)
- {
- m_currentFgIndex--;
- moveCurrentPage(false);
- }
- }
- else if (index > m_currentFgIndex) //点击右边的按钮 左移
- {
- while(index != m_currentFgIndex)
- {
- m_currentFgIndex++;
- moveCurrentPage(true);
- }
- }
- }
- void DataBrain::mouseMoveEvent(QMouseEvent *e)
- {
- int x = 0;
- if (m_mousePressFlag)
- {
- if (getLabelMove())
- {
- m_mouseDstPos = e->pos();
- x = m_mouseDstPos.x() - m_mouseSrcPos.x();
- setLabelMove(false);
- m_pLabelFg->move(m_currentFgXpos + x, WINDOW_START_Y);
- setLabelMove(true);
- }
- }
- else if (m_mouseMoveWindowFlag)
- {
- m_mouseDstPos = e->pos();
- this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos);
- }
- }
- void DataBrain::mouseReleaseEvent(QMouseEvent *e)
- {
- int xpos = 0;
- if (m_mousePressFlag)
- {
- if (getLabelMove())
- {
- m_mouseDstPos = e->pos();
- xpos = m_mouseDstPos.x() - m_mouseSrcPos.x();
- if (xpos > 0)//右移
- {
- if (xpos >= WINDOW_ONEBUTTON_WIDTH)
- {
- if (m_currentFgIndex > 0)
- {
- m_currentFgIndex--;
- moveCurrentPage(false); //右移
- }
- else
- {
- moveCurrentPage(true); //左移
- }
- }
- else
- {
- moveCurrentPage(true); //左移
- }
- }
- else //左移
- {
- if (xpos <= -WINDOW_ONEBUTTON_WIDTH)
- {
- if (m_currentFgIndex < WINDOW_PAGE_COUNT-1)
- {
- m_currentFgIndex++;
- moveCurrentPage(true); //左移
- }
- else
- {
- moveCurrentPage(false); //右移
- }
- }
- else
- {
- moveCurrentPage(false); //右移
- }
- }
- m_mousePressFlag = false;
- }
- }
- else if (m_mouseMoveWindowFlag)
- {
- m_mouseMoveWindowFlag = false;
- }
- }
- //快捷键
- void DataBrain::keyPressEvent(QKeyEvent *e)
- {
- if (getLabelMove())
- {
- switch(e->key())
- {
- case Qt::Key_Left:
- case Qt::Key_Up:
- if (m_currentFgIndex > 0)
- {
- m_currentFgIndex--;
- moveCurrentPage(false); //右移
- }
- break;
- case Qt::Key_Right:
- case Qt::Key_Down:
- if (m_currentFgIndex < WINDOW_PAGE_COUNT-1)
- {
- m_currentFgIndex++;
- moveCurrentPage(true); //左移
- }
- break;
- default:
- break;
- }
- }
- }
代码有点长,需要全部代码的可以去 http://download.csdn.net/detail/zhangyang1990828/5241242下载源代码。效果图就不上了,和360的新特性差不多。
通过这样一个例子,我想对于整个Qt的机制有了一定的了解吧,以后有好例子还会与大家分享的。
QT学习(五)----360界面制作(2终结)的更多相关文章
- qt学习 (五) 登陆界面之连接按钮
登陆步骤是比对输入的账号密码与数据库中的表项目是否一致 一样, 跳出mainwidget对话框 不一样,跳出消息错误框 今天就是要进去, 因为进去以后是widget的窗口,所以把用来核对消息的数据库 ...
- QT学习(四)----360界面制作(1)
参照网上的资料,模仿了一份360新特效的界面. 源代码在:http://download.csdn.net/detail/zhangyang1990828/5238013 360真实效果:(最好自己打 ...
- JFinal Web开发学习(五)注册界面和后端验证
效果: 直接点击注册后 : 后端验证是可靠地,前端js验证是不可靠的.只需要在浏览器删除js验证代码即可突破js验证. 1.注册界面 在WebRoot下新建regist.jsp <%@ page ...
- Qt之实现360安全卫士主界面代码开源
匆匆一年又过去了,总结去年一年的节奏就是忙爆了:生活忙.工作忙,值得庆幸的是没有瞎忙:今天打开博客园查看我的博客,才发现几乎差不多一年时间没写博客了:博客文章就是记忆,就是曾经努力过的见证,感谢博客园 ...
- 第15.10节 PyQt(Python+Qt)入门学习:Qt Designer可视化设计界面组件与QWidget类相关的组件属性详解
PyQt学习有阵子了,对章节的骨架基本考虑好了,准备本节就写组件的属性的,结果一是日常工作繁忙,经常晚上还要加班,二是Qt的组件属性很多,只能逐一学习.研究和整理,花的时间有点长,不过终于将可视化设计 ...
- qt学习笔记(五) QGraphicsPixmapItem与QGraphicsScene的编程实例 图标拖动渐变效果
应大家的要求,还是把完整的project文件贴出来,大家省点事:http://www.kuaipan.cn/file/id_48923272389086450.htm 先看看执行效果,我用的群创7寸屏 ...
- QT学习之windows下安装配置PyQt5
windows下安装配置PyQt5 目录 为什么要学习QT 命令行安装PyQt5以及PyQt5-tools 配置QtDesigner.PyUIC及PyRcc 为什么要学习QT python下与界面开发 ...
- QT学习2
一.常用控件与常用的功能函数. QDialog.QMainWindow.QPushButton.QLabel.QLineEdit 构造函数指定父容器.setText,getText,size,res ...
- Qt 学习之路 2(51):布尔表达式树模型
Qt 学习之路 2(51):布尔表达式树模型 豆子 2013年5月15日 Qt 学习之路 2 17条评论 本章将会是自定义模型的最后一部分.原本打算结束这部分内容,不过实在不忍心放弃这个示例.来自于 ...
随机推荐
- kubernetes之ingress探索实践
3.Ingress实践 3.1.什么是Ingress? 在ingress之前,我们想要访问k8s集群中的pod服务时,是通过部署一个service,将service的type设置为NodePort或者 ...
- C# --- SqlserverHelper帮助类、快速实现增删改查
using System;using System.Data; using System.Data.SqlClient; namespace Demo.WorkerService { public c ...
- 013(oulipo)
题目:http://ybt.ssoier.cn:8088/problem_show.php?pid=1455 题目描述:在母串里找子串出现的次数 题目思路:与字符串的搜索有关那就立刻找到哈希 从s[1 ...
- mysql实现两个字段合并成一个字段查询
[需求]实现国际化I18N语言切换功能,例如菜单列表.字典等. 主要是个辅助表进行管理语言的配置: 单个字段很简单,直接通过字典配置的数据标签(key)- 表名, 数据键值(value)-表字段名[默 ...
- C#《原CSharp》第三回 万文疑谋生思绪 璃月港口见清玉
第三回 万文疑谋生思绪 璃月港口见清玉 ===================================================================== 云溪愣了下,在他的认 ...
- javaScript去重的11种方法
前言 去重是开发和面试中经常遇到的问题,下面是总结的 11 种去重方法 方法 示例数组 var arr = [1, 2, 4, 5, 5, 2, 1, 1, 4, 6] set + 解构赋值 这种方法 ...
- Mac平台下git命令自动补全
一.安装bash-completion 安装Homebrew /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com ...
- 2022-7-12 javascript(2) 第七组 刘昀航
@ 目录 2022-7-12学习 第七组 刘昀航 前情提要 一.for循环 二.for in循环 三.while 和 do...while循环 1.while do... while 四.内置函数 五 ...
- S32K148_CAN驱动(裸机开发)
hello,大家好.今天我又来啦,今天记录一下S32K148-CAN裸机驱动编写,有错误地方欢迎大家指正. CAN的发送接收在S32K148中主要有三种方式,一种是邮箱机制(mailbox),一种FI ...
- 002面试题_Switch...case的数据
1.byte 2.short 3.int 4.char 5.String 6.枚举