首页/文章/ 详情

干货 | Qt中实现边加载数据边显示页面

1年前浏览487
*编辑注:

文章作者:稀土掘金“中国好公民st”

文章链接:

https://juejin.cn/post/7029852623268216845

做过C++开发的人们都知道,无论是MFC框架还是QT框架,实现加载数据的等待效果都是很麻烦的,不像WEB端轻轻松松一句代码就搞定了。而我们这些做C++的,最常用的方法就是开线程了。
刚开始,我也是采用的开线程的方式,但是,想象总是与事实相悖的。
假设页面展示的数据比较多,导致加载页面时间较长,用户体验度很差,点击了触发按钮之后很长时间才会有响应,总让人误会程序死机了,但真正的原因是数据正在加载。
那么,当前页面展示的数据量较多,我们该如何动态的显示边加载数据边显示页面呢?
对于我这种刚从MFC框架转过来的新手来说,确实是一个不小的挑战呢!
那么,我来讲解下我是如何实现的吧!

第一步:定义显示定时器

想要一打开页面就加载数据,我们需要重写QWidget::show(),开启定时器,并且要立即执行。
1:定义定时器
    //.h#include 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();}
          到这里,打开页面直接显示加载的功能已经完成了,那么该如何实现当前线程呢?
          接下来,是我们第二个阶段的内容了~

          第二步:线程加载数据

          一般C++的程序员在遇到这种情况时,通常很自然的就想要了,使用线程的方式。
          其实,我第一个思路也是使用线程加载数据。但是使用线程必须要考虑到线程存在的弊端,比如说死锁,比如说出现野指针等问题。
          在QT中有一种开线程的方式,简单容易上手,这里我还是比较推荐使用的:QtConcurrent::run
          该函数的具体讲解这里不做讲解,我们直接使用吧!
          首先需要的头文件:
            #include <QtConcurrent/QtConcurrentRun>
            接下来是调用方式,这里我们定义加载数据的函数名叫做LoadWidgetData()
              QFuture futureResult = QtConcurrent::run(this, &QMyWidget::LoadWidgetData);while (!futureResult.isFinished()){ QApplication::processEvents(QEventLoop::AllEvents);}
              使用这种线程方式的时候,需要注意了,LoadWidgetData函数的返回值一定是true才可以。
                bool QMyWidget::LoadWidgetData(){ //具体的数据加载操作 return true;}
                线程的加载方式已经介绍完了,到这里,我们已经可以实现一遍加载数据,一遍显示等待GIF效果了。
                接下来,我们该实现如何实时呈现加载进度了~

                第三步:实时呈现加载进度

                大家都知道,在QT的线程中是无法调用页面操作内容的。
                一般情况下的页面操作,比如窗口创建、控件赋值等等都需要在主线程进行,否则会造成崩溃问题。具体原因大家可以查阅资料去。
                那么,我们要实现边加载数据边在页面上展示的时候,该如何操作呢?
                在这里,我们可以用发消息的方式,在线程中发送消息给主进程,交给主进程处理页面操作
                  bool QMyWidget::LoadWidgetData(){ //1:加载数据内容1,具体实现不说明 //发送数据内容1对应的页面处理操作 emit Msg_SendSelfDataProcessing1(); //...数据加载内容自由发挥,类似于 上面两步骤内容 return true;}
                  代码看起来很好理解,这种方式既保证了数据加载流畅,也不对主页面造成卡顿现象。

                  深圳市优飞迪科技有限公司成立于2010年,是一家专注于产品开发平台解决方案与物联网技术开发的国家级高新技术企业。

                  十多年来,优飞迪科技在数字孪生、工业软件尤其仿真技术、物联网技术开发等领域积累了丰富的经验,并在这些领域拥有数十项独立自主的知识产权。同时,优飞迪科技也与国际和国内的主要头部工业软件厂商建立了战略合作关系,能够为客户提供完整的产品开发平台解决方案。

                  优飞迪科技技术团队实力雄厚,主要成员均来自于国内外顶尖学府、并在相关领域有丰富的工作经验,能为客户提供“全心U+端到端服务”。

                  来源:IFD优飞迪
                  数字孪生
                  著作权归作者所有,欢迎分享,未经许可,不得转载
                  首次发布时间:2023-02-03
                  最近编辑:1年前
                  优飞迪科技
                  赋能新仿真,创优新设计
                  获赞 301粉丝 243文章 334课程 4
                  点赞
                  收藏

                  作者推荐

                  未登录
                  还没有评论

                  课程
                  培训
                  服务
                  行家

                  VIP会员 学习 福利任务 兑换礼品
                  下载APP
                  联系我们
                  帮助与反馈