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:

[cpp] view plaincopyprint?
  1. enum EButtonMouseState  
  2. {  
  3.     EButtonMouseDefault = 0,  
  4.     EButtonMouseEnter,  
  5.     EButtonMousePress,  
  6.     EButtonMouseNone  
  7. };  
  8. void Preview360::createEventFilter()  
  9. {  
  10.     //安装事件过滤器   
  11.     m_pButtonClose->installEventFilter(this);  
  12. }  
  13. //设置按钮图标   
  14. void Preview360::setButtonIcon(QToolButton *btn, EButtonMouseState state)  
  15. {  
  16.     QPixmap pixmap(":/images/btn_close.png");  
  17.     int nWidth = pixmap.width()/4;  
  18.     int nHeight = pixmap.height();  
  19.     btn->setIcon(QIcon(pixmap.copy(QRect(state * nWidth, 0, nWidth, nHeight))));  
  20.     btn->setIconSize(QSize(nWidth, nHeight));  
  21. }  
  22. bool Preview360::eventFilter(QObject *target, QEvent *event)  
  23. {  
  24.     EButtonMouseState state = EButtonMouseNone;  
  25.     //对几种事件进行处理,这下载对Qt的事件过滤器,很清楚了,实践结合理论=...  
  26.     if (target == m_pButtonClose)  
  27.     {  
  28.         if (event->type() == QEvent::Enter)  
  29.         {  
  30.             state = EButtonMouseEnter;  
  31.         }  
  32.         else if (event->type() == QEvent::Leave)  
  33.         {  
  34.             state = EButtonMouseDefault;  
  35.         }  
  36.         else if (((QMouseEvent *)event)->button() == Qt::LeftButton)  
  37.         {  
  38.             if (event->type() == QEvent::MouseButtonPress)  
  39.             {  
  40.                 state = EButtonMousePress;  
  41.                 //若点击在关闭按钮上,不拖动图像  
  42.                 m_mousePressFlag = false;  
  43.             }  
  44.             else if (event->type() == QEvent::MouseButtonRelease)  
  45.             {  
  46.                 state = EButtonMouseDefault;  
  47.             }  
  48.         }  
  49.   
  50.         if (state != EButtonMouseNone)  
  51.         {  
  52.             setButtonIcon((QToolButton *)target, state);  
  53.         }  
  54.     }  
  55.     //处理完自定义拦截的事件,还要调用一次QWidget默认的事件过滤函数  
  56.     return QWidget::eventFilter(target, event);  
  57. }  


2.窗体的移动

窗体和图片的移动涉及到鼠标事件,只需事件鼠标的一些事件就可以达到预期的效果,主要的事件是:

[cpp] view plaincopyprint?
  1. void mousePressEvent(QMouseEvent *);  
  2. void mouseReleaseEvent(QMouseEvent *);  
  3. void mouseMoveEvent(QMouseEvent *);  


3.图片的移动
在操作上,有3个涉及到图片的移动:
(1).鼠标拖动图片
(2).鼠标拖动图片后,释放鼠标,图片恢复原位
(3).右键鼠标,图片右移
(4).键盘方向键控制图片的移动
(5).点击界面的4个按钮,分别移动到按钮对应的界面

4.关于鼠标控制的移动

这些主要是涉及到一些逻辑的代码,直接贴出:

[cpp] view plaincopyprint?
  1. void Preview360::mousePressEvent(QMouseEvent *e)  
  2. {  
  3.     if (e->button() == Qt::LeftButton)  
  4.     {  
  5.         m_mouseSrcPos = e->pos();  
  6.         //在y坐标小于40的区域,鼠标拖动使窗体移动   
  7.         if (m_mouseSrcPos.y() <= 40)  
  8.         {  
  9.             m_mouseMoveWindowFlag = true;  
  10.         }  
  11.         else  
  12.         {  
  13.         //大于40的区域,鼠标拖动使图片移动   
  14.             m_currentFgXpos = m_pLabelFgTotal->x();  
  15.             m_mousePressFlag = true;  
  16.         }  
  17.     }  
  18.     //右键鼠标,右移图片   
  19.     else if (e->button() == Qt::RightButton)  
  20.     {  
  21.         if (getLabelMove())  
  22.         {  
  23.             if (m_currentFgIndex > 0)  
  24.             {  
  25.                 m_currentFgIndex--;  
  26.                 moveCurrentPage(false); //右移  
  27.             }  
  28.         }  
  29.     }  
  30. }  
  31.   
  32. void Preview360::mouseReleaseEvent(QMouseEvent *e)  
  33. {  
  34.     int xpos = 0;  
  35.   
  36.     if (m_mousePressFlag)  
  37.     {  
  38.         if (getLabelMove())  
  39.         {  
  40.             m_mouseDstPos = e->pos();  
  41.   
  42.             xpos = m_mouseDstPos.x() - m_mouseSrcPos.x();  
  43.   
  44.             if (xpos > 0)//右移  
  45.             {  
  46.                 if (xpos >= WINDOW_ONEBUTTON_WIDTH)  
  47.                 {  
  48.                     if (m_currentFgIndex > 0)  
  49.                     {  
  50.                         m_currentFgIndex--;  
  51.                         moveCurrentPage(false); //右移  
  52.                     }  
  53.                     else  
  54.                     {  
  55.                         moveCurrentPage(true); //左移  
  56.                     }  
  57.                 }  
  58.                 else  
  59.                 {  
  60.                     moveCurrentPage(true); //左移  
  61.                 }  
  62.             }  
  63.             else //左移  
  64.             {  
  65.                 if (xpos <= -WINDOW_ONEBUTTON_WIDTH)  
  66.                 {  
  67.                     if (m_currentFgIndex < WINDOW_PAGE_COUNT-1)  
  68.                     {  
  69.                         m_currentFgIndex++;  
  70.                         moveCurrentPage(true); //左移  
  71.                     }  
  72.                     else  
  73.                     {  
  74.                         moveCurrentPage(false); //右移  
  75.                     }  
  76.                 }  
  77.                 else  
  78.                 {  
  79.                     moveCurrentPage(false); //右移  
  80.                 }  
  81.             }  
  82.   
  83.             m_mousePressFlag = false;  
  84.         }  
  85.     }  
  86.     else if (m_mouseMoveWindowFlag)  
  87.     {  
  88.         m_mouseMoveWindowFlag = false;  
  89.     }  
  90. }  
  91.   
  92. void Preview360::mouseMoveEvent(QMouseEvent *e)  
  93. {  
  94.     int x = 0;  
  95.   
  96.     if (m_mousePressFlag)  
  97.     {  
  98.         if (getLabelMove())  
  99.         {  
  100.             m_mouseDstPos = e->pos();  
  101.             x = m_mouseDstPos.x() - m_mouseSrcPos.x();  
  102.   
  103.             setLabelMove(false);  
  104.             m_pLabelFgTotal->move(m_currentFgXpos + x, WINDOW_START_Y);  
  105.             setLabelMove(true);  
  106.         }  
  107.     }  
  108.     else if (m_mouseMoveWindowFlag)  
  109.     {  
  110.         m_mouseDstPos = e->pos();  
  111.         this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos);  
  112.     }  
  113. }  


5.点击界面4个按钮进行移动

[cpp] view plaincopyprint?
  1. void Preview360::slotChangeCurrentPage(CLabel *label)  
  2. {  
  3.     int index = 0;  
  4.   
  5.     for (int i = 0; i < WINDOW_PAGE_COUNT; i++)  
  6.     {  
  7.         if (label == m_pLabelBtnArray[i])  
  8.         {  
  9.         //找出当前按钮的序号   
  10.             index = i;  
  11.             break;  
  12.         }  
  13.     }  
  14.   
  15.     //移动的几种可能性,对于x坐标   
  16.     //index=0, 将label移动到-680*0   
  17.     //index=1, 将label移动到-680*1  
  18.     //index=2, 将label移动到-680*2   
  19.     //index=3, 将label移动到-680*3  
  20.     //点击左边的按钮 右移   
  21.     if (index < m_currentFgIndex)  
  22.     {  
  23.         while(index != m_currentFgIndex)  
  24.         {  
  25.             m_currentFgIndex--;  
  26.             moveCurrentPage(false);  
  27.         }  
  28.     }  
  29.     else if (index > m_currentFgIndex) //点击右边的按钮 左移  
  30.     {  
  31.         while(index != m_currentFgIndex)  
  32.         {  
  33.             m_currentFgIndex++;  
  34.             moveCurrentPage(true);  
  35.         }  
  36.     }  
  37.     else  
  38.     {  
  39.         //...   
  40.     }  
  41. }  


6.键盘方向键的控制
捕捉对应的按键事件,只需重新实现键盘事件:
void keyPressEvent(QKeyEvent *);
左上键:图片右移
右下键:图片左移

[cpp] view plaincopyprint?
  1. void Preview360::keyPressEvent(QKeyEvent *e)  
  2. {  
  3.     if (getLabelMove())  
  4.     {  
  5.         switch(e->key())  
  6.         {  
  7.         case Qt::Key_Left:  
  8.         case Qt::Key_Up:  
  9.             if (m_currentFgIndex > 0)  
  10.             {  
  11.                 m_currentFgIndex--;  
  12.                 moveCurrentPage(false); //右移  
  13.             }  
  14.             break;  
  15.   
  16.         case Qt::Key_Right:  
  17.         case Qt::Key_Down:  
  18.             if (m_currentFgIndex < WINDOW_PAGE_COUNT-1)  
  19.             {  
  20.                 m_currentFgIndex++;  
  21.                 moveCurrentPage(true); //左移  
  22.             }  
  23.             break;  
  24.   
  25.         default:  
  26.             break;  
  27.         }  
  28.     }  
  29. }  


7.图片移动的关键函数
移动图片的具体函数,要缓慢的移动图片,也就是在循环里面延迟一下,并响应UI事件,防止界面冻结(未响应)。
在程序中,出现setLabelMove和getLabelMove函数,这两个函数主要是用来防止多个事件同时移动界面,导致错误。所以这里相当于给图片的移动加锁,保证移动操作的唯一性。

[cpp] view plaincopyprint?
  1. void Preview360::moveCurrentPage(bool direction)  
  2. {  
  3.     int currentXpos = 0;//当前label的x坐标  
  4.     int destXpos = 0;//目标x坐标  
  5.   
  6.     //改变当前页面对应的按钮   
  7.     changeCurrentButton();  
  8.   
  9.     //图片的几个分割点   
  10.     //0-680, 680-1360, 1360-2040, 2040-2720  
  11.     //真:向左移;  假:向右移   
  12.     if (direction)  
  13.     {  
  14.         //左移的几种可能性,对于x坐标   
  15.         //index=0, 将label移动到-680*0  
  16.         //index=1, 将label移动到-680*1   
  17.         //index=2, 将label移动到-680*2  
  18.         //index=3, 将label移动到-680*3   
  19.         setLabelMove(false);  
  20.         currentXpos = m_pLabelFgTotal->x();  
  21.         destXpos = -WINDOW_WIDTH * m_currentFgIndex;  
  22.         while(currentXpos > destXpos)  
  23.         {  
  24.             m_pLabelFgTotal->move(currentXpos-WINDOW_PAGE_MOVE, WINDOW_START_Y);  
  25.             currentXpos = m_pLabelFgTotal->x();  
  26.             qApp->processEvents(QEventLoop::AllEvents);  
  27.         }  
  28.         m_pLabelFgTotal->move(destXpos, WINDOW_START_Y);  
  29.         setLabelMove(true);  
  30.     }  
  31.     else  
  32.     {  
  33.         //右移的几种可能性,对于x坐标,与左移一致  
  34.         //index=0, 将label移动到-680*0   
  35.         //index=1, 将label移动到-680*1  
  36.         //index=2, 将label移动到-680*2   
  37.         //index=3, 将label移动到-680*3  
  38.         setLabelMove(false);  
  39.         currentXpos = m_pLabelFgTotal->x();  
  40.         destXpos = -WINDOW_WIDTH * m_currentFgIndex;  
  41.         while(currentXpos < destXpos)  
  42.         {  
  43.             m_pLabelFgTotal->move(currentXpos+WINDOW_PAGE_MOVE, WINDOW_START_Y);  
  44.             currentXpos = m_pLabelFgTotal->x();  
  45.             qApp->processEvents(QEventLoop::AllEvents);  
  46.         }  
  47.         m_pLabelFgTotal->move(destXpos, WINDOW_START_Y);  
  48.         setLabelMove(true);  
  49.     }  
  50. }  

防止界面冻结:
qApp->processEvents(QEventLoop::AllEvents);
该函数用来处理所有事件,保证了界面的正常运行。


8.将控件置顶
在最后补充下,要将需要的控件raise到栈顶:

[cpp] view plaincopyprint?
  1. //raise these widget   
  2. m_pLabelBg1->raise();  
  3. m_pButtonClose->raise();  
  4.   
  5. for (int i = 0; i < WINDOW_BUTTON_COUNT; i++)  
  6. {  
  7.     m_pLabelBtnArray[i]->raise();  
  8. }  

多个控件涉及到重叠的问题,只有这样重新调整栈顺序才能达到需要的效果。

源码下载地址:360新版特性界面

作者  : gzshun.
E-Mail: gzshuns#163.com (@)
转载请注明出处:http://blog.csdn.net/gzshun/article/details/7626756

原创粉丝点击