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

Qt實現(xiàn)炫酷啟動圖動態(tài)進度條效果

 更新時間:2021年11月16日 11:37:03   作者:朝十晚八  
最近接到一個新需求,讓做一個動效進度條。剛接手這個項目真的不知所措,后來慢慢理清思路,問題迎刃而解,下面小編通過本文給大家?guī)砹薗t實現(xiàn)炫酷啟動圖動態(tài)進度條效果,感興趣的朋友一起看看吧

一、簡述

最近接到一個新需求,讓做一個動效進度條。

由于我們的產(chǎn)品比較大,在軟件啟動的時候會消耗比較長的時間,原生的進度條已經(jīng)不能滿足我們的需求,這里我們就需要一個會動的進度條,效果如下圖所示。

光效進度條主要是做了一個進度動畫,在已完成的部分上進行快速的迭代渲染,給用戶一種直觀感受,我們的軟件一直努力加載,它還活著。

有了這個進度條之后,當(dāng)我們的進度從40%到50%這個持續(xù)的過程中,界面再也不會出現(xiàn)假死的情況,是不是很完美呢。。。

下面我就來分析下這個動效進度條是怎么做的

二、動效進度條

如效果圖所示,光效進度條不同于一般的進度條,他在基礎(chǔ)的任務(wù)進度之上還添加了一層光效,主要是想告訴用戶我們的軟件一直在努力運行,請在耐心的等待一下下。

我自己在做功能的時候,往往喜歡先做一個測試demo,然后在把做好的功能集成在正式環(huán)境,這個功能也不列外,如第一節(jié)中展示的效果圖,就是測試demo的樣子,雖然很丑,但是基礎(chǔ)功能是有的。

現(xiàn)在的很多軟件,在進度展示上都有了比較絢麗的效果,比如壓縮軟件,解壓文件的時候都會有動效進度條,用過的同學(xué)應(yīng)該都知道長啥樣,而我們的光效進度條跟這個效果差不多,除此之外我們還提供了另一種動效,延遲動效,他們兩個在一定程度上都展示了更友好的進度效果。

在開始分析功能前,首先我們先來考慮下我們的需求:動效進度條,也就是說在原來的進度條基礎(chǔ)上需要添加實時動畫,讓進度條看起來更炫酷一些,除了光效進度條以外,還有一種延遲到達進度條,也屬于動態(tài)進度條。

延遲動效、說直白一點兒就是延遲到達,當(dāng)我們設(shè)置了進度從10%到20%時,程序模擬了一個漸進的過程,使用一個時間段走完了這10%的進度。

下面我們分別來介紹這兩種進度條的實現(xiàn)

實現(xiàn)炫酷的進度條我們可以從QWidget自定義開始寫,也就是說從頭開始寫,但通常我們不這樣干,因為這樣可能會寫出無窮無盡的bug,而且現(xiàn)有的輪子已經(jīng)很穩(wěn)定了,為什么還要造呢。

1、光效進度條

光效進度條我們使用了一個小技巧,采用一個簡單的辦法實現(xiàn),我們的光效進度條控件繼承自Qt原生進度條類QProgressBar,在新類中我們只需要在Qt繪制完原生進度條之后,補畫動效即可。

a、paintEvent函數(shù)

paintEvent函數(shù)是Qt的繪制函數(shù),當(dāng)界面刷新的時候,這個接口函數(shù)就會被調(diào)用,因此我們需要重寫這個接口,首先調(diào)用父窗口的繪制方法,然后我們在繪制我們自己的動效,代碼如下所示

QProgressBar::paintEvent(event);
drawCache繪制動效

b、drawCache繪制動效

繪制動效的時候,我們需要知道動效的繪制區(qū)域,這個地方我們需要主動去解析qss的一些參數(shù),Qt的style()->subElementRect這個接口剛好可以拿到我們需要的信息

下面簡單描述下我們的實現(xiàn)流程

  • 首先我們獲取進度條的幾何大小和中間進度的幾何大小,這樣的話我們就可以計算出來各border的數(shù)值
  • 然后根據(jù)我們當(dāng)前的value值就可以計算出進度條已經(jīng)走過(就是值小于我們設(shè)定的區(qū)域)的幾何大小
  • 我們的光效將是跑在第二步計算出來的區(qū)域上,一直循環(huán)迭代
  • 內(nèi)存里我們維護一個cacheValue,這個值在每次界面刷新的時候遞增,但是不能大于第二步的value值,cacheValue將是我們動效繪制的一個關(guān)鍵參數(shù),他表示了動效繪制的長度
  • 構(gòu)造一個漸變刷子,設(shè)置給QPainter
  • 繪制動效

上下大致描述了下繪制動效的一個流程,下面送上具體代碼,由于篇幅原因,代碼我進行了部分偽代碼處理。

void GMPProgressBar::drawCache()
{
    QStyleOptionProgressBarV2 opt;
    QRect outerRect = style()->subElementRect(QStyle::SE_ProgressBarGroove, &opt, this);
    QRect innerRect = style()->subElementRect(QStyle::SE_ProgressBarContents, &opt, this);
    QMargins borders(構(gòu)造一個QMargins);

	QRectF rect(動效繪制區(qū)域);

	if (m_iCacheValue != 0)
	{
		QPainter painter(this);
		QLinearGradient gradient(構(gòu)造繪圖刷子);
		painter.setBrush(gradient);
		painter.drawRoundedRect(rect, 2, 2);
	}
}

c、定時刷新

由于我們的動效是需要主動去刷新的,因此我們需要聲明一個定時器,然后定時去刷新,實現(xiàn)代碼可能像下面這樣

connect(m_pCacheTimer, &QTimer::timeout, this, [this]{
		if (TM_CACHE == m_mode)
		{
			++m_iCacheValue;
			repaint();
		}else
        {
            m_pCacheTimer->stop();
        }
	});

定時器只需要在我們第一次設(shè)置進度條值的時候啟動,或者當(dāng)我們設(shè)置一個新的值,而定時器沒有啟動,我們就需要去激活定時器。

TM_CACHE模式即是我們的動效模式,TM_SMOOTH模式則是我們的延遲到達模式

connect(this, &QProgressBar::valueChanged, [this](int value){//TM_CACHE模式下 啟動動畫時機
		if (!m_pCacheTimer->isActive() && value != 0 && TM_CACHE == m_mode)
		{
			m_pCacheTimer->start(m_iRefreshleveling);
		}
	});

動效進度條效果如下圖所示

2、延遲到達進度條

動效進度條可能更適用于啟動界面,但是也有一些時候,我們可能需要更平緩的一個加載曲線,例如安裝軟件、卸載軟件的時候。

a、setValue

延遲到達進度條和動效進度條的實現(xiàn)方式就有所差別了,對于實現(xiàn)延遲到達進度條,我們這里重寫了setValue函數(shù),當(dāng)外部調(diào)用該接口設(shè)置value值時,我們并沒有立即去設(shè)置當(dāng)前值,而是使用了一個時間段去完成這個值得刷新。

  • 外部調(diào)用setValue時,我們首先計算出我們應(yīng)該繪制的最大寬度PixelMax、當(dāng)前已經(jīng)繪制到的最大寬度cacheValue和我們的步長
  • 設(shè)置定時器刷新頻率,并重啟定時器
  • 定時器刷新時,cacheValue自增我們的步長
  • 調(diào)用父類的QProgressBar::setValue接口設(shè)置值

b、定時器

延遲達到功能的的定時器和之前我們什么的動效定時器可以混用一個,我們定時器刷新的時候,針對不同的動畫模式,我們執(zhí)行不同的的代碼即可,實現(xiàn)代碼可能像下面這樣

connect(m_pCacheTimer, &QTimer::timeout, this, [this]{
	if (TM_CACHE == m_mode)
	{
		++m_iCacheValue;
		repaint();
	}
	else if (TM_SMOOTH == m_mode)
	{
		changeSmooth();
	}
    else
    {
        m_pCacheTimer->stop();
    }
});

延遲到達進度條效果如下圖所示

3、接口說明

光效進度條類對外只暴露了3個接口,分別是設(shè)置動畫模式、動畫時長和刷新頻率

特別需要注意的是,我們這里重寫了父類的setValue接口,這意味著我們不能使用多態(tài)來操作這個接口

void setTransitionMode(TransitionMode mode);//設(shè)置動畫模式
void setSmoothDuration(int duration);//設(shè)置刷新總時長 模式為TM_SMOOTH時有效
void setRefreshleveling(int rate);//設(shè)置刷新頻率 每次更改TransitionMode之后會變?yōu)槟J值

a、修改動畫模式

修改動畫模式的時候,我們需要清空內(nèi)存中的所有數(shù)據(jù),并把value值設(shè)為0。

void GMPProgressBar::setTransitionMode(TransitionMode mode)
{
	if (m_mode == mode)
	{
		return;
	}

	m_mode = mode;
	clearData();

	QProgressBar::setValue(0);
}

b、其他接口

設(shè)置刷新時長和頻率接口都比較簡單,不做特別說明

特別注意:這個3個接口最好是在動畫啟動前設(shè)置,動畫開始后盡量不要去調(diào)用

三、啟動圖

第二節(jié)我們主要是講述了怎么做一個動效進度條,這一節(jié)我們來做一個啟動圖頁面,把這個動效使用進去。

啟動圖不是我們主要分析的內(nèi)容,這個我就簡單說下這個類的實現(xiàn)方式和一些借口說明

1、實現(xiàn)思路

Qt已經(jīng)給我們提供了一個QSplashScreen,但是使用起來還是特別有限,因此這里我把Qt的源碼直接進行了二次開發(fā)

  • 首先Qt的原生實現(xiàn)方式基本都被移植了出來
  • 啟動圖使用了簡單的上下布局,上面是一張我自繪制的圖片,放在了一個QLabel上,下面是動效進度條
  • 自繪制的圖片上包括了,產(chǎn)品名稱、logo、背景圖等等

2、背景圖切換

當(dāng)我們調(diào)用setPixmap設(shè)置背景圖時,如果我們指定了多張圖,我將會啟動一個定時器,在指定時長后重新構(gòu)造一張大的背景圖,并添加到啟動窗口上

這里主要說明下背景圖是怎么構(gòu)造出來的,代碼如下所示

a、根據(jù)背景圖構(gòu)造啟動圖大小,并移動到屏幕中間

m_currentPixmap = m_lstPixmaps.at(m_iCurrentIndex);

QRect size(QPoint(), m_currentPixmap.size()  / m_currentPixmap.devicePixelRatio());
size.setHeight(size.height() + StatusBarHeight);
setFixedSize(size.size());
m_pProgressBar->setFixedWidth(size.width() / 8 * 3);
move(QApplication::desktop()->screenGeometry().center() - size.center());

b、繪制程序logo

QPainter painter(&m_currentPixmap);
painter.drawPixmap(m_startPos, m_logo);

c、繪制標題欄

painter.save();
painter.setFont(m_titleFont);

QFontMetrics fontMetrics(m_titleFont);
int textWidth = fontMetrics.width(m_strWindowTitle);
int textHegith = m_logo.height();
QRect textTect = QRect(m_startPos + QPoint(13 + m_logo.width(), 0), QSize(textWidth, textHegith));
painter.drawText(textTect, m_strWindowTitle, QTextOption(Qt::AlignCenter));
painter.restore();

d、設(shè)置給QLabel背景圖

m_pWindowBackground->setPixmap(m_currentPixmap);

啟動圖的效果這里就不在貼圖了,第三節(jié)上的兩個gif圖都是最終的啟動圖效果

四、測試

最后就是測試代碼了,主要是模擬了程序的一個加載過程

1、構(gòu)造啟動圖

首先我們構(gòu)造一個啟動圖對象,并設(shè)置程序logo和動畫模式

GMPSplashScreen * screen = new GMPSplashScreen(QPixmap(":/splashScreen/start.png"));
screen->show();
screen->setLogo(QIcon("logo.ico").pixmap(48, 48));
screen->setTransitionMode(GMPProgressBar::TM_CACHE);

2、背景圖

設(shè)置背景圖,并設(shè)置背景圖更換時間間隔

QList<QPixmap> lstPixmap;
lstPixmap.append(QPixmap(":/splashScreen/start.png"));
lstPixmap.append(QPixmap(":/splashScreen/start.jpg"));
screen->setPixmap(lstPixmap, 2000);

3、其他信息

設(shè)置程序的提示信息和標題欄

screen->showMessage("Established connections", 0);
screen->setTitle(QStringLiteral("廣聯(lián)達BIM土建計量GTJ2018"));

4、事件循環(huán)

這里寫了一個死循環(huán),主要是為了模擬程序的一個加載過程,每隔10ms處理下界面刷新事件

a.processEvents();

while (1)
{
    QTest::qSleep(10);
    a.processEvents();
}
splashScreen w;
w.show();

screen->finish(&w);

五、源碼

需要源碼的留郵箱,現(xiàn)在的csdn簡直太坑爹了。。。

到此這篇關(guān)于Qt實現(xiàn)炫酷啟動圖動態(tài)進度條效果的文章就介紹到這了,更多相關(guān)Qt動態(tài)進度條內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Python3使用tesserocr識別字母數(shù)字驗證碼的實現(xiàn)

    Python3使用tesserocr識別字母數(shù)字驗證碼的實現(xiàn)

    這篇文章主要介紹了Python3使用tesserocr識別字母數(shù)字驗證碼的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01
  • Python調(diào)用C# Com dll組件實戰(zhàn)教程

    Python調(diào)用C# Com dll組件實戰(zhàn)教程

    下面小編就為大家?guī)硪黄狿ython調(diào)用C# Com dll組件實戰(zhàn)教程。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-10-10
  • OpenAI的Whisper模型進行語音識別使用詳解

    OpenAI的Whisper模型進行語音識別使用詳解

    這篇文章主要介紹了OpenAI的Whisper模型進行語音識別使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-02-02
  • pytorch打印網(wǎng)絡(luò)結(jié)構(gòu)的實例

    pytorch打印網(wǎng)絡(luò)結(jié)構(gòu)的實例

    今天小編就為大家分享一篇pytorch打印網(wǎng)絡(luò)結(jié)構(gòu)的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-08-08
  • Django框架多表查詢實例分析

    Django框架多表查詢實例分析

    這篇文章主要介紹了Django框架多表查詢,結(jié)合實例形式分析了Django框架實現(xiàn)多表查詢的外鍵、關(guān)聯(lián)、前向查詢、反向查詢等相關(guān)操作技巧與注意事項,需要的朋友可以參考下
    2018-07-07
  • pycharm 2020.2.4 pip install Flask 報錯 Error:Non-zero exit code的問題

    pycharm 2020.2.4 pip install Flask 報錯 Error:Non-zero exit co

    這篇文章主要介紹了pycharm 2020.2.4 pip install Flask 報錯 Error:Non-zero exit code,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • PyTorch實現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)的搭建詳解

    PyTorch實現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)的搭建詳解

    這篇文章主要為大家介紹了PyTorch實現(xiàn)卷積神經(jīng)網(wǎng)絡(luò)的搭建詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-05-05
  • python加載自定義詞典實例

    python加載自定義詞典實例

    今天小編就為大家分享一篇python加載自定義詞典實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2019-12-12
  • django用戶注冊、登錄、注銷和用戶擴展的示例

    django用戶注冊、登錄、注銷和用戶擴展的示例

    本篇文章主要介紹了django用戶注冊、登錄、注銷和用戶擴展的示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • 詳解Python中__new__和__init__的區(qū)別與聯(lián)系

    詳解Python中__new__和__init__的區(qū)別與聯(lián)系

    在Python中,每個對象都有兩個特殊的方法:__new__和__init__,本文將詳細介紹這兩個方法的不同之處以及它們之間的聯(lián)系,具有一定的參考價值,感興趣的可以了解一下
    2023-12-12

最新評論

锡林浩特市| 临城县| 望江县| 遂平县| 三江| 都兰县| 南华县| 新营市| 陇川县| 西贡区| 大石桥市| 桐乡市| 沁源县| 天柱县| 南靖县| 西华县| 巫溪县| 黄陵县| 淮滨县| 和田市| 长顺县| 新巴尔虎左旗| 河西区| 新野县| 仁寿县| 宝兴县| 恩平市| 陕西省| 五峰| 乐清市| 平顺县| 历史| 苏尼特左旗| 许昌市| 大宁县| 梁平县| 杨浦区| 云林县| 寿光市| 五家渠市| 安岳县|