当前位置: 首页 > news >正文

[旧日谈]关于Qt的刷新事件频率,以及我们在Qt的框架上做实时的绘制操作时我们该关心什么。

[旧日谈]关于Qt的刷新事件频率,以及我们在Qt的框架上做实时的绘制操作时我们该关心什么。

最近在开发的时候,发现一个依赖事件来刷新渲染的控件会导致程序很容易异常和崩溃。

当程序在运行的时候,其实软件本身的负载并不高,所以在Demo下运行一切良好(良好吗?),但是时装到实际项目下,就发现程序异常崩溃。

后面经过几轮排查,我们发现由这个控件造成的,因为控件的刷新频率太高了。

先来说说这个控件。这个控件的操作实际上依赖了Qt的moveEvent,当鼠标按下之后,然后鼠标移动会触发moveEvent,则这个控件会跟随鼠标移动。这个控件在移动了之后,一下子数据就多到把整个数据流顶爆了。

请添加图片描述

我一开始并没有想过这个问题,因为我想的是我这边渲染没问题,框架上的事情按理说就不用我关心了。但是在我的测试和开发中,我发现事情远没有这么简单。

函数计时

为什么要提到函数计时,因为这里控件的操作我需要做一个计时操作,来检测到底是哪里耗时过多。

我这里的界面并不是只管自己发布数据,而是连着很多个控件一起刷新,这就导致了一个问题。我发现其实我在其他控件上进行移动和检查花费的事件更多更频繁。

至于我是如何发现的,我这里分享一个RAII型的计时器,用于计算一个函数从开始到结束的总时间


class TimeCounter {
public:TimeCounter(const QString& FunctionName) {if (PublicVar::ins().blnCountingTimeMode) {qDebug() << "Function Begin at : " << FunctionName;this->functionName = FunctionName;timer.start();}};~TimeCounter() {if (PublicVar::ins().blnCountingTimeMode) {qDebug() << " Function " << this->functionName << "time used with :" << timer.elapsed() << "milliseconds.";}}
private:QElapsedTimer timer;QString functionName;
};

使用范例:

void function(){TimeCounter timer(__FUNCTION__);QThread::msleep(10);
}

刷新率?

既然我这个函数是依赖moveEvent来刷新界面的,也就是说我这个函数调用的频率是严格与moveEvent的刷新频率同步的。但是moveEvent的刷新率是多少?这个问题我完全没有考虑过。

显然,这个moveEvent的刷新率应该是大于60的,因为我在60hz的屏幕上完全感受不到卡顿。但那具体是多高?

moveEvent的刷新频率与鼠标的刷新率有关

是的,你没看错,moveEvent的刷新频率与鼠标的刷新率有关。在这里我可以做一个函数,来对moveEvent的刷新率进行一个简单的测算。

QtWidgetsApplication3.h

#pragma once#include <QtWidgets/QMainWindow>
#include "ui_QtWidgetsApplication3.h"
#include "qtimer.h"
class QtWidgetsApplication3 : public QMainWindow
{Q_OBJECTpublic:QtWidgetsApplication3(QWidget *parent = nullptr);~QtWidgetsApplication3();QTimer* timer;
protected:void moveEvent(QMoveEvent* event) override;
private:size_t m_moveEventCount = 0;void onTimerTimeout();Ui::QtWidgetsApplication3Class ui;
};

QtWidgetsApplication3.cpp


#include "QtWidgetsApplication3.h"QtWidgetsApplication3::QtWidgetsApplication3(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);this->timer = new QTimer(this);connect(timer, &QTimer::timeout, this, &QtWidgetsApplication3::onTimerTimeout);timer->start(1000); // 每1000毫秒(1秒)触发一次
}QtWidgetsApplication3::~QtWidgetsApplication3()
{}
#include "qdebug.h"
void QtWidgetsApplication3::moveEvent(QMoveEvent * event)
{QMainWindow::moveEvent(event); // 确保调用基类的 moveEvent 函数// 递增计数器m_moveEventCount++;
}void QtWidgetsApplication3::onTimerTimeout()
{// 打印 moveEvent 每秒触发的次数qDebug() << "moveEvent count per second:" << m_moveEventCount;// 重置计数器m_moveEventCount = 0;
}

测试结果:

1.鼠标回报率125hz

刷新率大概在126times/s

2.鼠标回报率250hz

刷新率大概在250times/s

3.鼠标回报率500hz

刷新率大概在400tick/s

4. 鼠标回报率1000hz

刷新率大概在400tick/s,最高可以到700tick/s

这个负载完全把我吓了一跳,因为我这里实际上根本用不到这么高的刷新率,对于一般的产品来说,30-60hz 的刷新率已经可以让整个产品看起来堪称流畅了,特别是这种性能关键而且和很多控件连带的地方。

结论

如果控件是依赖moveEvent来刷新界面的,那么这个控件的刷新频率就会依赖鼠标的刷新频率。如果那个地方的控件移动对后台进行的操作比较耗时,数据量比较大的时候,或者这个控件连带着很多空间一起操作的时候,可能会需要考虑到鼠标分辨率的影响。

http://www.lryc.cn/news/460028.html

相关文章:

  • 云上考场小程序+ssm论文源码调试讲解
  • 城域网——IP城域网、城域以太网、光城域网
  • 华为Eth-trunk链路聚合加入到E-trunk实现跨设备的链路聚合
  • 【网络安全】JSONP劫持原理及攻击实战
  • VR全景摄影的拍摄和编辑软件推荐
  • linux:使用sar诊断问题
  • CUDA编程技巧(不断搜集更新)
  • 云计算(第二阶段):mysql后的shell
  • Debian12离线部署Mysql全网最详细教程
  • 文本生成视频技术:艺术与科学的交汇点
  • 【Windows】【DevOps】Windows Server 2022 采用WinSW将一个控制台应用程序作为服务启动(方便)
  • OpenAI董事会主席Bret Taylor的Agent公司Sierra:专注于赋能下一代企业用户体验
  • 【linux】信号(下)
  • Notepad++ 初学者指南
  • Web Socket 使用详解
  • 【Python Web开发】Python Web开发知识全解析
  • Android开发展开收起功能
  • Sealos Devbox 发布,珍爱生命,远离 CI/CD
  • 数据结构——遍历二叉树
  • 【Ubuntu】在Ubuntu上安装IDEA
  • 解决:gpg: 从公钥服务器接收失败:服务器故障
  • 支持向量机SVM
  • 斯坦福UE4 C++课学习补充25:AI感知组件
  • 大模型 memory 记忆 缓存的应用
  • perl 给特定文件加上特定内容
  • 全面解析网络性能监控系统与网络故障排除技巧,助力IT运维高效管理
  • Centos7 搭建单机elasticsearch
  • 【前端】Bootstrap:JavaScript 组件与插件
  • 部署 Open WebUI
  • HUAWEI_HCIA_实验指南_Lib2.1_交换机基础配置