Qt實現邊加載數據邊顯示頁面的示例代碼

做過C++開發的人們都知道,無論是MFC框架還是QT框架,實現加載數據的等待效果都是很麻煩的,不像WEB端輕輕松松一句代碼就搞定瞭。而我們這些做C++的,最常用的方法就是開線程瞭。

剛開始,我也是采用的開線程的方式,但是,想象總是與事實相悖的。

假設頁面展示的數據比較多,導致加載頁面時間較長,用戶體驗度很差,點擊瞭觸發按鈕之後很長時間才會有響應,總讓人誤會程序死機瞭,但真正的原因是數據正在加載。

那麼,當前頁面展示的數據量較多,我們該如何動態的顯示邊加載數據邊顯示頁面呢?

對於我這種剛從MFC框架轉過來的新手來說,確實是一個不小的挑戰呢!

那麼,我來講解下我是如何實現的吧!

1.定義顯示定時器

想要一打開頁面就加載數據,我們需要重寫QWidget::show(),開啟定時器,並且要立即執行。

1:定義定時器

//.h
#include <QTimer>

QTimer *m_Timer;

//.cpp使用
m_Timer = new QTimer(this);
connect(m_Timer, &QTimer::timeout, this, &QMyWidget::OnTimerLoadData);

2:定時器調用

void QMyWidget::show()
{
    QWidget::show();
    m_timer->start(0);
}

打開頁面需要立即執行定時器操作,此時start中的參數=0,表示立即執行。

此時,顯示頁面已經加載出來瞭。

因為前面說過瞭,頁面的數據量比較多,不可能顯示頁面之後處於假死的狀態,那麼,我們需要加載頁面的同時,顯示一個gif的等待圖標。

這裡,我們就需要修改一下show()的函數

void QMyWidget::show()
{
    QWidget::show();
    //頁面啟動後,直接顯示加載gif圖片
    gPageManager::instance()->GetDownloadDlg()->SetShowMode(1);
    gPageManager::instance()->GetDownloadDlg()->SetTips("正在加載案例數據,請稍後...");
    gPageManager::instance()->GetDownloadDlg()->show();
    if (m_timer->isActive() == false)
    {
        m_timer->start(0);    
    }
}

這裡,我用瞭一個單例類:gPageManager調用具有gif效果圖的窗口。

這種方式就可以實現,顯示頁面以後,直接等待數據加載,防止我們看到假死頁面,給用戶造成困惱。

這裡的gif圖片是用一個QLabel承載顯示的,方法很多,不過多介紹。

這裡提醒的是:在使用QT中的定時器,比較安全的做法是,判斷該定時是否處於活躍狀態,隻有再非活躍狀態下才需要觸發。這裡隻做溫馨提示哦,個人代碼習慣而已~

3:定時器加載數據

當進入定時器之後,進行數據處理。為瞭防止頁面卡頓,此時,在定時器中我們也要重新開啟一個線程,用於數據加載。

此時,就會有人想問,當前頁面已經開啟瞭一個定時器,為什麼還要再創建一個線程呢?

下面我會一一解答的。

在C語言的函數中,運行指定函數中的內容時,隻有運行到"}"時,才會顯示運行頁面。在某個特定的具體處理函數中計算機在處理時屬於一個過程處理函數。

所以,才會在一顯示頁面就開啟定時器操作,首先將頁面展示給用戶,在做其他的數據處理。

那麼為什麼要在定時器中再開一個線程呢?

主要是因為在show函數中調用瞭一個動態加載的窗口,假設定時器中直接加載較多數據時,此時,界面也會處於一個卡頓狀態,導致GIF等待窗口被卡住。為瞭防止這種情況出現,我們需要在定時器中繼續開一個線程,防止頁面卡頓。

void QMyWidget::OnTimerLoadData()
{
    //因為隻是在打開頁面時加載數據,所以,定時器隻需要進行一次即可。
    m_Timer->stop();
    
    //啟動線程,加載數據,具體代碼這裡不具體說明。
    
    //數據加載完之後,隱藏GIF動態加載頁面
    gPageManager::instance()->GetDownloadDlg()->hide();
}

到這裡,打開頁面直接顯示加載的功能已經完成瞭,那麼該如何實現當前線程呢?

接下來,是我們第二個階段的內容瞭~

2.線程加載數據

一般C++的程序員在遇到這種情況時,通常很自然的就想要瞭,使用線程的方式。

其實,我第一個思路也是使用線程加載數據。但是使用線程必須要考慮到線程存在的弊端,比如說死鎖,比如說出現野指針等問題。

在QT中有一種開線程的方式,簡單容易上手,這裡我還是比較推薦使用的:QtConcurrent::run

該函數的具體講解這裡不做講解,我們直接使用吧!

首先需要的頭文件:

#include <QtConcurrent/QtConcurrentRun>

接下來是調用方式,這裡我們定義加載數據的函數名叫做LoadWidgetData()

QFuture<bool> futureResult = QtConcurrent::run(this, &QMyWidget::LoadWidgetData);
while (!futureResult.isFinished())
{
    QApplication::processEvents(QEventLoop::AllEvents);
}

使用這種線程方式的時候,需要註意瞭,LoadWidgetData函數的返回值一定是true才可以

bool QMyWidget::LoadWidgetData()
{
    //具體的數據加載操作
    return true;
}

線程的加載方式已經介紹完瞭,到這裡,我們已經可以實現一遍加載數據,一遍顯示等待GIF效果瞭。

接下來,我們該實現如何實時呈現加載進度瞭~

3.實時呈現加載進度

大傢都知道,在QT的線程中是無法調用頁面操作內容的。

一般情況下的頁面操作,比如窗口創建、控件賦值等等都需要在主線程進行,否則會造成崩潰問題。具體原因大傢可以查閱資料去。

那麼,我們要實現邊加載數據邊在頁面上展示的時候,該如何操作呢?

在這裡,我們可以用發消息的方式,在線程中發送消息給主進程,交給主進程處理頁面操作

bool QMyWidget::LoadWidgetData()
{
    //1:加載數據內容1,具體實現不說明
    
    //發送數據內容1對應的頁面處理操作
    emit Msg_SendSelfDataProcessing1();
    
    //...數據加載內容自由發揮,類似於 上面兩步驟內容
    
    return true;
}

代碼看起來很好理解,這種方式既保證瞭數據加載流暢,也不對主頁面造成卡頓現象。

到此這篇關於Qt實現邊加載數據邊顯示頁面的示例代碼的文章就介紹到這瞭,更多相關Qt內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: