Qt日记(3)-360新版特性界面实现(3)
来源:互联网 发布:java 字符流读取文件 编辑:程序博客网 时间:2024/05/18 20:36
转自:http://blog.csdn.net/gzshun/article/details/7626756
1.画关闭按钮
拖动图片的功能放后面说,先把关闭按钮给画出来。
现在很多软件,类似QQ,360,91助手......等等软件,界面上都有很多很漂亮的按钮,当鼠标移上去,按钮变为高亮,当鼠标点击下去,按钮变为暗色凹下,当鼠标移开,按钮又恢复原来的样子。
这效果都是由多张图片切换而来的。
new出一个QToolButton,设置关闭按钮图标。按钮图片一般都以4种状态提供,将4张图片拼成1张png。所以每次只需取出图片中的1/4就行,然后将关闭按钮移动到右上角。
想在Qt中实现这3种效果,很简单,只需在窗体中安装事件过滤器即可。
涉及到函数:eventFilter, installEventFilter.
几种按钮的enum:
- enum EButtonMouseState
- {
- EButtonMouseDefault = 0,
- EButtonMouseEnter,
- EButtonMousePress,
- EButtonMouseNone
- };
- void Preview360::createEventFilter()
- {
- //安装事件过滤器
- m_pButtonClose->installEventFilter(this);
- }
- //设置按钮图标
- void Preview360::setButtonIcon(QToolButton *btn, EButtonMouseState state)
- {
- QPixmap pixmap(":/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));
- }
- bool Preview360::eventFilter(QObject *target, QEvent *event)
- {
- EButtonMouseState state = EButtonMouseNone;
- //对几种事件进行处理,这下载对Qt的事件过滤器,很清楚了,实践结合理论=...
- if (target == m_pButtonClose)
- {
- 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;
- //若点击在关闭按钮上,不拖动图像
- m_mousePressFlag = false;
- }
- else if (event->type() == QEvent::MouseButtonRelease)
- {
- state = EButtonMouseDefault;
- }
- }
- if (state != EButtonMouseNone)
- {
- setButtonIcon((QToolButton *)target, state);
- }
- }
- //处理完自定义拦截的事件,还要调用一次QWidget默认的事件过滤函数
- return QWidget::eventFilter(target, event);
- }
enum EButtonMouseState{ EButtonMouseDefault = 0, EButtonMouseEnter, EButtonMousePress, EButtonMouseNone};void Preview360::createEventFilter(){ //安装事件过滤器 m_pButtonClose->installEventFilter(this);}//设置按钮图标void Preview360::setButtonIcon(QToolButton *btn, EButtonMouseState state){ QPixmap pixmap(":/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));}bool Preview360::eventFilter(QObject *target, QEvent *event){ EButtonMouseState state = EButtonMouseNone; //对几种事件进行处理,这下载对Qt的事件过滤器,很清楚了,实践结合理论=... if (target == m_pButtonClose) { 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; //若点击在关闭按钮上,不拖动图像 m_mousePressFlag = false; } else if (event->type() == QEvent::MouseButtonRelease) { state = EButtonMouseDefault; } } if (state != EButtonMouseNone) { setButtonIcon((QToolButton *)target, state); } } //处理完自定义拦截的事件,还要调用一次QWidget默认的事件过滤函数 return QWidget::eventFilter(target, event);}
2.窗体的移动
窗体和图片的移动涉及到鼠标事件,只需事件鼠标的一些事件就可以达到预期的效果,主要的事件是:
- void mousePressEvent(QMouseEvent *);
- void mouseReleaseEvent(QMouseEvent *);
- void mouseMoveEvent(QMouseEvent *);
void mousePressEvent(QMouseEvent *);void mouseReleaseEvent(QMouseEvent *);void mouseMoveEvent(QMouseEvent *);
3.图片的移动
在操作上,有3个涉及到图片的移动:
(1).鼠标拖动图片
(2).鼠标拖动图片后,释放鼠标,图片恢复原位
(3).右键鼠标,图片右移
(4).键盘方向键控制图片的移动
(5).点击界面的4个按钮,分别移动到按钮对应的界面
4.关于鼠标控制的移动
这些主要是涉及到一些逻辑的代码,直接贴出:
- void Preview360::mousePressEvent(QMouseEvent *e)
- {
- if (e->button() == Qt::LeftButton)
- {
- m_mouseSrcPos = e->pos();
- //在y坐标小于40的区域,鼠标拖动使窗体移动
- if (m_mouseSrcPos.y() <= 40)
- {
- m_mouseMoveWindowFlag = true;
- }
- else
- {
- //大于40的区域,鼠标拖动使图片移动
- m_currentFgXpos = m_pLabelFgTotal->x();
- m_mousePressFlag = true;
- }
- }
- //右键鼠标,右移图片
- else if (e->button() == Qt::RightButton)
- {
- if (getLabelMove())
- {
- if (m_currentFgIndex > 0)
- {
- m_currentFgIndex--;
- moveCurrentPage(false); //右移
- }
- }
- }
- }
- void Preview360::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 Preview360::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_pLabelFgTotal->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 Preview360::mousePressEvent(QMouseEvent *e){ if (e->button() == Qt::LeftButton) { m_mouseSrcPos = e->pos(); //在y坐标小于40的区域,鼠标拖动使窗体移动 if (m_mouseSrcPos.y() <= 40) { m_mouseMoveWindowFlag = true; } else { //大于40的区域,鼠标拖动使图片移动 m_currentFgXpos = m_pLabelFgTotal->x(); m_mousePressFlag = true; } } //右键鼠标,右移图片 else if (e->button() == Qt::RightButton) { if (getLabelMove()) { if (m_currentFgIndex > 0) { m_currentFgIndex--; moveCurrentPage(false); //右移 } } }}void Preview360::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 Preview360::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_pLabelFgTotal->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); }}
5.点击界面4个按钮进行移动
- void Preview360::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);
- }
- }
- else
- {
- //...
- }
- }
void Preview360::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); } } else { //... }}
6.键盘方向键的控制
捕捉对应的按键事件,只需重新实现键盘事件:
void keyPressEvent(QKeyEvent *);
左上键:图片右移
右下键:图片左移
- void Preview360::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;
- }
- }
- }
void Preview360::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; } }}
7.图片移动的关键函数
移动图片的具体函数,要缓慢的移动图片,也就是在循环里面延迟一下,并响应UI事件,防止界面冻结(未响应)。
在程序中,出现setLabelMove和getLabelMove函数,这两个函数主要是用来防止多个事件同时移动界面,导致错误。所以这里相当于给图片的移动加锁,保证移动操作的唯一性。
- void Preview360::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_pLabelFgTotal->x();
- destXpos = -WINDOW_WIDTH * m_currentFgIndex;
- while(currentXpos > destXpos)
- {
- m_pLabelFgTotal->move(currentXpos-WINDOW_PAGE_MOVE, WINDOW_START_Y);
- currentXpos = m_pLabelFgTotal->x();
- qApp->processEvents(QEventLoop::AllEvents);
- }
- m_pLabelFgTotal->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_pLabelFgTotal->x();
- destXpos = -WINDOW_WIDTH * m_currentFgIndex;
- while(currentXpos < destXpos)
- {
- m_pLabelFgTotal->move(currentXpos+WINDOW_PAGE_MOVE, WINDOW_START_Y);
- currentXpos = m_pLabelFgTotal->x();
- qApp->processEvents(QEventLoop::AllEvents);
- }
- m_pLabelFgTotal->move(destXpos, WINDOW_START_Y);
- setLabelMove(true);
- }
- }
void Preview360::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_pLabelFgTotal->x(); destXpos = -WINDOW_WIDTH * m_currentFgIndex; while(currentXpos > destXpos) { m_pLabelFgTotal->move(currentXpos-WINDOW_PAGE_MOVE, WINDOW_START_Y); currentXpos = m_pLabelFgTotal->x(); qApp->processEvents(QEventLoop::AllEvents); } m_pLabelFgTotal->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_pLabelFgTotal->x(); destXpos = -WINDOW_WIDTH * m_currentFgIndex; while(currentXpos < destXpos) { m_pLabelFgTotal->move(currentXpos+WINDOW_PAGE_MOVE, WINDOW_START_Y); currentXpos = m_pLabelFgTotal->x(); qApp->processEvents(QEventLoop::AllEvents); } m_pLabelFgTotal->move(destXpos, WINDOW_START_Y); setLabelMove(true); }}
防止界面冻结:
qApp->processEvents(QEventLoop::AllEvents);
该函数用来处理所有事件,保证了界面的正常运行。
8.将控件置顶
在最后补充下,要将需要的控件raise到栈顶:
- //raise these widget
- m_pLabelBg1->raise();
- m_pButtonClose->raise();
- for (int i = 0; i < WINDOW_BUTTON_COUNT; i++)
- {
- m_pLabelBtnArray[i]->raise();
- }
//raise these widgetm_pLabelBg1->raise();m_pButtonClose->raise();for (int i = 0; i < WINDOW_BUTTON_COUNT; i++){ m_pLabelBtnArray[i]->raise();}
多个控件涉及到重叠的问题,只有这样重新调整栈顺序才能达到需要的效果。
源码下载地址:360新版特性界面
作者 : gzshun.
E-Mail: gzshuns#163.com (@)
转载请注明出处:http://blog.csdn.net/gzshun/article/details/7626756
- Qt日记(3)-360新版特性界面实现(3)
- Qt日记(3)-360新版特性界面实现(3)
- Qt日记(3)-360新版特性界面实现(3)
- Qt日记(1)-360新版特性界面实现(1)
- Qt日记(2)-360新版特性界面实现(2)
- Qt日记(1)-360新版特性界面实现(1)
- Qt日记(2)-360新版特性界面实现(2)
- Qt日记(1)-360新版特性界面实现
- 360新版特性界面实现(3)
- 360新版特性界面实现(1)
- 360新版特性界面实现(2)
- Qt界面美化3
- 仙侣奇缘3新版登录器界面设定
- MFC界面库BCGControlBar v25.3新版亮点:Gauge Controls
- 【QT】:QT实现登录界面
- Qt之实现360安全卫士主界面
- Qt实现360卫士相关界面
- Qt实现360安全卫士9.2界面
- Dos命令汇总
- java中cookie的操作(通过cookie实现简单的单点登录)
- 英语学习7
- 深度比较Java循环的性能
- 单源最短路径(Dijkstra算法,贪心算法的应用)
- Qt日记(3)-360新版特性界面实现(3)
- 流概念 抽取与插入
- VS2012下基于Glut OpenGL GL_TRIANGLE_STRIP示例程序:
- 字符串全攻略
- UIDatePicker中英文显示
- G14刷机
- CString 成员函数用法大全
- java 实现完数
- Ubuntu的环境变量