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);}
2.表單的移動
表單和圖片的移動涉及到滑鼠事件,只需事件滑鼠的一些事件就可以達到預期的效果,主要的事件是:
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); }}
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 { //... }}
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; } }}
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); }}
防止介面凍結:
qApp->processEvents(QEventLoop::AllEvents);
該函數用來處理所有事件,保證了介面的正常運行。
8.將控制項置頂
在最後補充下,要將需要的控制項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