如何为无法获取进度百分比的耗时操作增加“伪进度条”?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何为无法获取进度百分比的耗时操作增加“伪进度条”?相关的知识,希望对你有一定的参考价值。

在实际开发中,可能会遇到这样的场景:“一个操作非常耗时,但却无法获取其进度百分比”。造成这种情况的原因可能有: 
1)该操作属于第三方库(泛指我们使用但无法修改的第三方代码,因此质量有高有底),可能由于第三方库作者没有意识到这个操作在某些情况下会非常耗时,没有提供进度值。 
2)某些操作压根就无法计算进度或者计算进度要牺牲极大的效率。

这种场景,执行这样的耗时操作会导致程序UI假死。为了提高用户体验,我们可以为该操作提供一个假的进度条,即保证程序UI不假死。我们将耗时操作放到子线程中去执行,然后在GUI主线程中抛出一个进度对话框,用一个定时器每隔0.5秒(或者一个更合适的值)更新进度条的百分比。用一个循环待子线程执行完毕则GUI主线程继续往下执行。

void MainWindow::slotRun()
{
    QProgressDialog progressDlg(tr("正在读取文件..."), tr("取消"),
                                0, 100, this,
                                Qt::CustomizeWindowHint);
    progressDlg.setWindowModality(Qt::WindowModal);
    progressDlg.setMinimumSize(400, 100);
    progressDlg.show(); // 进度对话框在GUI主线程中执行

    FileReader aFileReader("D:/BigFile.txt");
    FunctionRunThread runThread(aFileReader);  // 将耗时操作放到子线程中去执行
    runThread.start();
    int cnt = 0; // 循环次数计数器,用于"计算"当前的进度值
    while (!runThread.isFinished())  // 只要子线程还没有完成,就一直循环,并更新进度条
    {
        //QThread::currentThread()->wait(500);
        //QApplication::instance()->thread()->wait(500);

        progressDlg.setValue((cnt++%20)*5); // 进度值每次递增5%,达到100后则再次从0开始

        QEventLoop eventloop; // 使用事件循环阻塞主线程
        QTimer::singleShot(500, &eventloop, SLOT(quit())); // wait 0.5s
        eventloop.exec(); // 每0.5秒执行一次事件循环,然后更新进度条
    }
    progressDlg.setValue(100);
    qDebug() << "cnt=" << cnt;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

偶然看到一个更高级的实现方式: 
http://wiki.qt.io/Progress_Bar

http://blog.csdn.net/e5max/article/details/50441148

以上是关于如何为无法获取进度百分比的耗时操作增加“伪进度条”?的主要内容,如果未能解决你的问题,请参考以下文章

Ajax上传文件

如何为 iOS 项目设置最低代码覆盖率阈值?

在Linux操作系统的纯命令行界面,如rpm -ivh或者scp这些命令使用时会出现进度条和百分比,如何用shell实现

android进度条怎么显示百分比

两个进度条,加上百分比显示(用WPF实现)

在vuex中带进度条的FIie上传