Qt日記(3)-360新版特性介面實現(3)
轉自: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 widget
m_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
相關文章
- 32.qt quick-模仿QQ登入介面實現3D旋轉(Rotation、Flipable)QTUI3D
- js和css3實現360旋轉滾動效果JSCSSS3
- 3月21日學習日記
- 3月22日學習日記
- 日記3(immutable.js)JS
- pytorch實現yolov3(3) 實現forwardPyTorchYOLOForward
- 記3月7日面試面試
- 介面3
- CSS/CSS3語法新特性筆記CSSS3筆記
- 深度解析DDR3記憶體特性記憶體
- java 介面,介面的特性,介面實現多型,面向介面程式設計Java多型程式設計
- 介面自動化之實現日誌記錄封裝封裝
- 筆記3:自定義註解的實現筆記
- OpenCV筆記(3)實現支援向量機(SVM)OpenCV筆記
- SpringBoot3整合SpringDoc實現線上介面文件Spring Boot
- 3月23日學習筆記筆記
- 3月25日學習筆記筆記
- 軟體工程開發日記3軟體工程
- QT筆記之實現陰影視窗QT筆記
- Qt 實現 Logger 日誌的顯示QT
- 32.qt quick-PathView實現好看的home介面QTUIView
- 從零開始實現放置遊戲(五)——實現掛機戰鬥(3)引入日誌功能並實現切面日誌遊戲
- CSS3實現3D魔方效果CSSS33D
- CSS3實現3D翻牌效果CSSS33D
- Vue3 新特性Vue
- css3 新特性CSSS3
- CSS3-其它特性CSSS3
- CSS3新特性CSSS3
- qcad qt ecmajavascript sqlite3QTJavaScriptSQLite
- Selenium3與Python3實戰Web自動化測試框架【日記1】PythonWeb框架
- 360前端星計劃-深入css(3)前端CSS
- OkHttp3+mysql+jenkin 現介面自動化HTTPMySql
- 3D Touch 實現3D
- 小白的LeetCode日記記錄Day3LeetCode
- CSS3實現3d效果照片牆CSSS33D
- android nfc tag3 除錯日記Android除錯
- 3月24日廣州DBA課程筆記筆記
- qt 單獨執行緒實現日誌寫入功能QT執行緒