最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Qt重寫(xiě)QStackedWidget模擬實(shí)現(xiàn)home界面滑動(dòng)效果

 更新時(shí)間:2022年11月29日 17:06:06   作者:音視頻開(kāi)發(fā)老舅  
這篇文章主要為大家詳細(xì)介紹了Qt如何通過(guò)重寫(xiě)QStackedWidget模擬實(shí)現(xiàn)home界面滑動(dòng)效果,文中的實(shí)現(xiàn)過(guò)程講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

在上章我們學(xué)習(xí)了QScroller實(shí)現(xiàn)home界面滑動(dòng)效果,但是該界面是實(shí)現(xiàn)的上下滑動(dòng)效果,如果想模擬手機(jī)home滑動(dòng)界面,則需要實(shí)現(xiàn)左右滑動(dòng)效果.

本章,則重寫(xiě)QStackedWidget類(lèi),來(lái)真正的模擬手機(jī),來(lái)實(shí)現(xiàn)home界面左右滑動(dòng)效果.

1.SmoothStackedWidget類(lèi)實(shí)現(xiàn)

demo界面如下圖所示(創(chuàng)建了4個(gè)子界面):

 (支持快滑,慢滑):

如果是慢滑,則根據(jù)當(dāng)前滑到的界面處于哪一頁(yè)占比更多,則就跳到哪里.

否則就是快滑,根據(jù)滑動(dòng)的偏移值來(lái)決定跳轉(zhuǎn)

同樣也支持邊緣滑動(dòng)檢測(cè)(已在最邊緣時(shí),則滑動(dòng)速率減慢,告訴用戶(hù)已到邊緣):

2.代碼實(shí)現(xiàn)

頭文件如下所示:

#ifndef SMOOTHSTACKEDWIDGET_H
#define SMOOTHSTACKEDWIDGET_H
 
#include <QObject>
#include <QWidget>
#include <QStackedWidget>
#include <QAbstractScrollArea>
#include <QPixmap>
#include <QPropertyAnimation>
 
class SmoothStackedWidget : public QStackedWidget
{
    Q_OBJECT
 
#define SMOOTH_MAX_MS   900                   //平滑滑動(dòng)時(shí)的最大延遲時(shí)間
#define SMOOTH_EDGE_MOVE_RATIO   0.14         //邊緣移動(dòng)系數(shù),范圍0~1,越低越慢
 
    typedef enum tagScrollMouseDragInfo {
          MOUSE_RELEASE = 0,                       //鼠標(biāo)離開(kāi)
          MOUSE_PRESS = 1,                         //按下
          MOUSE_PRESS_MOVE = 2,                    //按下移動(dòng)
          MOUSE_RELEASE_MOVE = 3                   //鼠標(biāo)離開(kāi)并滑動(dòng)
    }Scroll_Mouse_Drag_INFO_E;
 
    typedef enum tagSmoothAnimationSwitchInfo {
          SWITCH_PRE = -1,                      //切換上一頁(yè)
          SWITCH_NONE = 0,                      //不切換
          SWITCH_NEXT = 1,                      //切換下一頁(yè)
    }AnimationSwitch_Drag_INFO_E;
 
    Scroll_Mouse_Drag_INFO_E m_dragFlag = MOUSE_RELEASE;
    AnimationSwitch_Drag_INFO_E m_switchFlag = SWITCH_NONE;
  
    QWidget *m_parent;
 
    QWidget m_smoothWidget;
 
    int m_smoothCurrentIndex=-1;
 
    QPropertyAnimation *animation;
 
    float m_smoothMovePos;
 
    bool eventFilter(QObject *obj, QEvent *evt) override;
 
    void paintEvent(QPaintEvent *event) override;
 
    void resizeEvent(QResizeEvent *event) override;
 
    void SmoothLoadPixmap(bool isSmoothUpdate = false);
    void SmoothStartMove();
 
    void SmoothMove(int offset);
 
    void SmoothAnimationStart(int startPos, int endPos, int durationMs);
 
    void SmoothAnimationInit();
 
public:
    explicit SmoothStackedWidget(QWidget *parent = nullptr);
 
    int addWidget(QAbstractScrollArea *w);
 
    int addWidget(QWidget *w);
 
    void setCurrentIndex(int index);
 
    void removeWidget(QWidget *w);
 
    void IconUpdate();      //刷新頁(yè)數(shù)標(biāo)簽
 
    void UpdateSmooth();
 
signals:
 
protected slots:
    void OnSmoothAnimationFinished();
 
};
 
#endif // SMOOTHSTACKEDWIDGET_H

其中eventFilter()函數(shù)如下所示:

當(dāng)鼠標(biāo)(手指)按下移動(dòng)時(shí),則調(diào)用SmoothMove(offset),通過(guò)offset來(lái)動(dòng)態(tài)顯示滑動(dòng)的界面.

當(dāng)鼠標(biāo)(手指)松開(kāi)后,則調(diào)用SmoothAnimationStart()來(lái)實(shí)現(xiàn)界面移動(dòng)(到底是切換上一頁(yè)、還是切換下一頁(yè)、還是當(dāng)前頁(yè)).

bool SmoothStackedWidget::eventFilter(QObject *obj, QEvent *evt)
{
    QMouseEvent *mouse =  dynamic_cast<QMouseEvent *>(evt);
    QWidget *w =  dynamic_cast<QWidget *>(obj);
 
    static int pressPoint_x   = 0;          //按下的坐標(biāo)
    static int dragPoint_x    = -1;         //拖動(dòng)時(shí)的坐標(biāo)
    static qint64 pressMSec ;
 
    if(mouse && w && animation->state() == QAbstractAnimation::Stopped)
    {
         if( mouse->type() ==QEvent::MouseButtonPress)    //首次按下
        {
           pressMSec = QDateTime::currentDateTime().toMSecsSinceEpoch();     //記錄按下的時(shí)間
           dragPoint_x  = mouse->pos().x();               //當(dāng)前坐標(biāo)
           pressPoint_x = dragPoint_x;                    //按下的位置
           m_dragFlag = MOUSE_PRESS;
        }
         else if(mouse->type() == QEvent::MouseButtonRelease &&
                 m_dragFlag == MOUSE_PRESS)               //未移動(dòng)
        {
           m_dragFlag = MOUSE_RELEASE;
        }
         else if(mouse->type() == QEvent::MouseMove &&
                 m_dragFlag == MOUSE_PRESS)               //初次滑動(dòng),判斷移動(dòng)閥值,避免誤操作
        {
            if(qAbs(dragPoint_x - mouse->pos().x()) > 3)     //判斷移動(dòng)閥值,避免誤操作
            {
               dragPoint_x = mouse->pos().x();
               SmoothStartMove();
               m_dragFlag = MOUSE_PRESS_MOVE;
            }
        }
         else if(mouse->type() == QEvent::MouseMove &&
                 m_dragFlag== MOUSE_PRESS_MOVE )             //正在滑動(dòng)
        {
            int offset = ( mouse->pos().x() - dragPoint_x);
            SmoothMove(offset);
            dragPoint_x = mouse->pos().x();
        }
        else if(mouse->type() == QEvent::MouseButtonRelease &&
                m_dragFlag == MOUSE_PRESS_MOVE)               //滑動(dòng)結(jié)束,啟動(dòng)平滑滑動(dòng)
        {
             int durationMs= QDateTime::currentDateTime().toMSecsSinceEpoch()-pressMSec;
             SmoothAnimationStart(pressPoint_x,mouse->pos().x(),durationMs);
             m_dragFlag = MOUSE_RELEASE;
        }
    }
 
    return QWidget::eventFilter(obj,evt);
}

SmoothAnimationStart()函數(shù)如下所示:

void  SmoothStackedWidget::SmoothAnimationStart(int startPos, int endPos, int durationMs)
{
    int pixelPerSecond=qAbs(endPos - startPos)*1000/durationMs;       //計(jì)算每秒像素點(diǎn)
    m_switchFlag = SWITCH_NONE;
    int moveX = qAbs(m_smoothWidget.x());
    float temp = width()*0.5;
    int animationEndX;
 
    //慢速滑動(dòng)(速度過(guò)慢||時(shí)間過(guò)長(zhǎng)),則根據(jù)當(dāng)前滑到哪里,就跳到哪里
    if(pixelPerSecond<300 || durationMs > 1000) {
        if(moveX < (temp)) {        //[0,width/2] = 上一頁(yè)
            if(currentIndex()==0) {
                animationEndX = -width();
            } else {
                animationEndX = 0;
                m_switchFlag = SWITCH_PRE;
            }
        } else if(moveX < (temp*3)) {    //[width/2,width*3/2] = 當(dāng)前一頁(yè)
            animationEndX = -width();
        } else {
            if(currentIndex()==(count()-1)) {   //[width*3/2,width*2] = 下一頁(yè)
                animationEndX = -width();
            } else {
                animationEndX = -width()*2;
                m_switchFlag = SWITCH_NEXT;
            }
        }
 
    } else {    // 否則就是快速滑動(dòng)
        if(startPos < endPos) { //向右滑動(dòng)
            if(currentIndex()==0) {
                animationEndX = -width();
            } else {
                animationEndX = 0;
                m_switchFlag = SWITCH_PRE;
            }
        } else {         //向左滑動(dòng)
            if(currentIndex()==(count()-1)) {
                animationEndX = -width();
            } else {
                animationEndX = -width()*2;
                m_switchFlag = SWITCH_NEXT;
            }
        }
    }
 
    //根據(jù)每秒滑動(dòng)像素點(diǎn),來(lái)計(jì)算滑動(dòng)時(shí)長(zhǎng).
    int animationDuration = durationMs;
    float xOffsetRatio = qAbs(animationEndX - m_smoothWidget.x()) / (static_cast<float>(width())); //計(jì)算滑動(dòng)占整屏比例
 
    if(animationDuration > (SMOOTH_MAX_MS * xOffsetRatio)) //滑動(dòng)時(shí)間過(guò)大,則重置
        animationDuration = SMOOTH_MAX_MS * xOffsetRatio;
 
 
    animation->setDuration(animationDuration);
    animation->setStartValue(m_smoothWidget.geometry());
    animation->setEndValue(QRect(animationEndX, m_smoothWidget.y(), m_smoothWidget.width(), m_smoothWidget.height()));
    animation->start();
}

到此這篇關(guān)于Qt重寫(xiě)QStackedWidget模擬實(shí)現(xiàn)home界面滑動(dòng)效果的文章就介紹到這了,更多相關(guān)Qt QStackedWidget界面滑動(dòng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 如何用C語(yǔ)言畫(huà)一個(gè)“圣誕樹(shù)”

    如何用C語(yǔ)言畫(huà)一個(gè)“圣誕樹(shù)”

    這篇文章主要介紹了如何用C語(yǔ)言畫(huà)一個(gè)“圣誕樹(shù)”,感興趣的小伙伴們可以參考一下
    2015-12-12
  • C語(yǔ)言進(jìn)階:指針的進(jìn)階(2)

    C語(yǔ)言進(jìn)階:指針的進(jìn)階(2)

    這篇文章主要介紹了C語(yǔ)言指針詳解及用法示例,介紹了其相關(guān)概念,然后分享了幾種用法,具有一定參考價(jià)值。需要的朋友可以了解下
    2021-09-09
  • C++實(shí)現(xiàn)四則混合運(yùn)算計(jì)算器

    C++實(shí)現(xiàn)四則混合運(yùn)算計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則混合運(yùn)算計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-11-11
  • Matlab繪制有趣的羅盤(pán)時(shí)鐘的示例代碼

    Matlab繪制有趣的羅盤(pán)時(shí)鐘的示例代碼

    這篇文章主要介紹了如何利用Matlab實(shí)現(xiàn)繪制有趣的羅盤(pán)時(shí)鐘,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Matlab有一定的幫助,需要的可以參考一下
    2023-01-01
  • Qt中Qfile類(lèi)的使用

    Qt中Qfile類(lèi)的使用

    很多應(yīng)用程序都具備操作文件的能力,包括對(duì)文件進(jìn)行寫(xiě)入和讀取,創(chuàng)建和刪除文件,本文主要介紹了Qt中Qfile類(lèi)的使用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-05-05
  • C/C++中退出線程的四種解決方法

    C/C++中退出線程的四種解決方法

    本篇文章是對(duì)C/C++中退出線程的四種解決方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Qt定時(shí)器類(lèi)QTimer使用詳解與注意事項(xiàng)

    Qt定時(shí)器類(lèi)QTimer使用詳解與注意事項(xiàng)

    Qt提供了兩種定時(shí)器,一種是QObject類(lèi)的定時(shí)器,另一種是QTimer類(lèi)的定時(shí)器,這篇文章主要給大家介紹了關(guān)于Qt定時(shí)器類(lèi)QTimer使用與注意事項(xiàng)的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • C語(yǔ)言實(shí)現(xiàn)貪吃蛇超詳細(xì)教程

    C語(yǔ)言實(shí)現(xiàn)貪吃蛇超詳細(xì)教程

    本文詳細(xì)講解了C語(yǔ)言實(shí)現(xiàn)貪吃蛇的方法,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-12-12
  • C語(yǔ)言實(shí)現(xiàn)惡作劇關(guān)機(jī)程序

    C語(yǔ)言實(shí)現(xiàn)惡作劇關(guān)機(jī)程序

    大家好,本篇文章主要講的是C語(yǔ)言實(shí)現(xiàn)惡作劇關(guān)機(jī)程序,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話記得收藏一下
    2022-01-01
  • 使用Matlab制作簡(jiǎn)易版八分音符醬游戲

    使用Matlab制作簡(jiǎn)易版八分音符醬游戲

    八分音符醬作為一款聲音控制類(lèi)游戲,當(dāng)時(shí)還是很受大家的喜愛(ài)的。本文將用Matlab制作一款簡(jiǎn)易版的八分音符醬游戲,感興趣的可以學(xué)習(xí)一下
    2022-02-02

最新評(píng)論

都安| 盘山县| 紫阳县| 马龙县| 武冈市| 溆浦县| 满洲里市| 招远市| 巫溪县| 沈丘县| 类乌齐县| 清涧县| 娄底市| 历史| 陆川县| 新和县| 临湘市| 海淀区| 抚顺市| 武穴市| 嘉义县| 宜黄县| 古浪县| 普陀区| 石柱| 独山县| 石台县| 瓦房店市| 平舆县| 香格里拉县| 黔西县| 石渠县| 上犹县| 介休市| 紫云| 吉林省| 清流县| 澎湖县| 电白县| 福鼎市| 浦北县|