Qt/C++ 波形绘制双缓冲下改善PaintEvent连续绘制卡顿问题(完整代码解析)

  1. 音频波形可视化:该控件用于将音频样本数据可视化为波形,常用于音频处理软件中以展示音频信号的时间域特性。

  2. 动态数据绘制:控件能够响应外部数据的变化并重新绘制波形,适用于实时或动态的音频数据流。

  3. 自定义绘制逻辑:通过Qt的绘图API,特别是QPainterQPainterPath,实现了波形的自定义绘制,包括线条的平滑、颜色渐变以及路径的描绘。

  4. 性能优化:通过双缓冲技术(使用QPixmap)和适当的数据处理,减少了绘制过程中的计算量,提高了渲染效率。

  5. 颜色编码:使用颜色渐变来区分波形的不同振幅区域,比如使用红色到蓝色的渐变表示波形的高低振幅,绿色表示零点线,使得波形的阅读更直观。

  6. 可扩展性:控件为Qt框架下的自定义控件,可以很容易地集成到更大的Qt应用程序中,并根据需求进行定制和扩展。

    
    #ifndef WAVEFORMWIDGET_H
    #define WAVEFORMWIDGET_H
    
    #include <QWidget>
    #include <QPixmap>
    
    class WaveformWidget : public QWidget {
        Q_OBJECT
    
    public:
        explicit WaveformWidget(QWidget *parent = nullptr);
        ~WaveformWidget();
        void setSamples(const QList<float> &newSamples);
    
    protected:
        void paintEvent(QPaintEvent *event) override;
        void resizeEvent(QResizeEvent *event) override;
    
    private:
        QList<float> samples; // 用于存储音频样本的列表
        QPixmap buffer; // 双缓冲的画布
        void redrawBuffer(); // 在画布上重新绘制波形
    };
    
    #endif // WAVEFORMWIDGET_H
    #include "WaveformWidget.h"
    #include <QPainter>
    #include <QResizeEvent>
    
    WaveformWidget::WaveformWidget(QWidget *parent)
        : QWidget(parent) {
        // 初始化双缓冲画布
        buffer = QPixmap(size());
        buffer.fill(Qt::black);
    }
    
    WaveformWidget::~WaveformWidget() {
    }
    
    void WaveformWidget::setSamples(const QList<float> &newSamples) {
        samples = newSamples;
        redrawBuffer(); // 更新画布
    }
    
    void WaveformWidget::paintEvent(QPaintEvent *event) {
        QPainter painter(this);
        painter.drawPixmap(0, 0, buffer);
    }
    
    void WaveformWidget::resizeEvent(QResizeEvent *event) {
        // 调整画布大小并重新绘制
        buffer = QPixmap(event->size());
        buffer.fill(Qt::black);
        redrawBuffer();
    }
    
    void WaveformWidget::redrawBuffer() {
        // 确保画布准备好
        if (buffer.size() != size()) {
            buffer = QPixmap(size());
        }
    
        QPainter painter(&buffer);
        painter.setRenderHint(QPainter::Antialiasing);
    
        // 重置画布背景
        buffer.fill(Qt::black);
    
        if (samples.isEmpty()) return;
    
        const int middleY = buffer.height() / 2;
        const int upperLimit = middleY / 2;  // -50 to 50 对应的 Y 坐标
        const int lowerLimit = middleY + upperLimit;
    
        // 创建路径和描边路径
        QPainterPath path, strokePath;
        path.moveTo(0, middleY);
    
        qreal xStep = static_cast<qreal>(buffer.width()) / (samples.size() - 1);
    
        // 根据样本数据构造波形路径
        for (int i = 0; i < samples.size(); ++i) {
            qreal x = i * xStep;
            qreal y = middleY - (samples.at(i) * middleY / 100.0);
            path.lineTo(x, y);
            strokePath.lineTo(x, y);
        }
    
        // 绘制渐变
        QLinearGradient gradient(0, 0, 0, buffer.height());
        gradient.setColorAt(0.0, QColor(255, 0, 0));    // 顶部为红色
        gradient.setColorAt(0.25, QColor(0, 0, 255));   // 中部为蓝色
        gradient.setColorAt(0.5, Qt::transparent);      // 中间透明
        gradient.setColorAt(0.75, QColor(0, 0, 255));   // 中部为蓝色
        gradient.setColorAt(1.0, QColor(255, 0, 0));    // 底部为红色
    
        QPen pen(gradient, 2);
        painter.setPen(pen);
        painter.drawPath(strokePath);
    
        // 绘制中间的零点线
        QPen centerLinePen(Qt::green);
        centerLinePen.setWidth(1);
        painter.setPen(centerLinePen);
        painter.drawLine(0, middleY, buffer.width(), middleY);
    
        // 请求更新控件
        update();
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/578774.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git操作与异常处理

文章目录 常用操作1、代码拉取2、代码提交3、暂存区状态4、提交代码5、推送远程仓库 异常处理【1】报错信息&#xff1a;Cannot pull into a repository with state: MERGING【2】报错信息&#xff1a;You have not concluded your merge (MERGE_HEAD exists)【3】报错信息&…

SpringCloud整合Ribbon负载均衡器

目录 一、模块一&#xff1a;提供数据 1.1 首先将第一个实例打包 1.2 使用命令行设置不同权重 1.3 打开图形化界面看看权重是否配置成功。 二、模块二&#xff1a;调用模块一 三、修改默认负载均衡策略 四、自定义规则 ​编辑 五、完整代码 5.1 目录结构 5.2 配置文件 …

Stable Diffusion学习线路,提示词及资源分享

1. 提示词的基础概念 提示词分为正面提示词&#xff08;Prompts&#xff09;和反面提示词&#xff08;Negative Prompts&#xff09;。正面提示词代表你希望画面中出现的内容&#xff0c;而反面提示词代表你不希望画面中出现的内容。提示词通常是以英文书写&#xff0c;最小单…

新版本Qt Creator安装配置

新版本Qt Creator安装配置 文章目录 新版本Qt Creator安装配置1、前言2、环境3、安装配置4、总结 更多精彩内容&#x1f449;个人内容分类汇总 &#x1f448;&#x1f449;Qt开发经验 &#x1f448; 1、前言 Qt是一个跨平台的C应用程序开发框架&#xff0c;而Qt Creator是专为Q…

树,二叉树的基本概念介绍,二叉树的性质

目录 树 树的定义 树的相关概念 树的存储结构 树在实际中的运用&#xff08;表示文件系统的目录树结构 &#xff09; 二叉树 二叉树的定义 现实中的二叉树 二叉树的特点 特殊的二叉树 1.斜树 2.满二叉树 3.完全二叉树 二叉树的性质 性质1&#xff1a;二叉树的第…

数字旅游引领智慧化浪潮:科技创新重塑旅游体验,智慧服务打造旅游新高度

在科技飞速发展的今天&#xff0c;数字旅游正以其独特的魅力引领着智慧化浪潮&#xff0c;深刻改变着旅游行业的面貌。数字技术的广泛应用&#xff0c;不仅为旅游行业注入了新的活力&#xff0c;也极大地提升了旅游体验的品质。科技创新与智慧服务的融合&#xff0c;正推动着旅…

大厂面试题:两道来自京东的关于MyBatis执行器的面试题

大家好&#xff0c;我是王有志。 今天给大家带来两道来自于京东关于的 MyBatis 面试题&#xff1a; MyBatis 提供了哪些执行器&#xff08;Executor&#xff09;&#xff1f;它们有什么区别&#xff1f;Mybatis 中如何指定 Executor 的类型&#xff1f; MyBatis 提供了哪些执…

【VBA】获取指定目录下的Excel文件,并合并所有excel中的内容。

1.新建一个excel表格。并创建两个Sheet&#xff0c;名字分别命名为FileList 和 All information。 2.按ALTF11进入 VBA编程模块&#xff0c;插入模块。 3.将如下 第五部分代码复制到模块中。 点击运行即可&#xff0c;然后就能提取指定目录下的所有excel文件信息并合并到一起…

plsql 新建sql窗口 初始化慢的问题

问题描述&#xff1a; 新建sql窗口当sql语句多的情况下初始化很慢。 解决方法&#xff1a; 采用导入表的方式。 具体方式 工具->导入表->sql插入。 使用命令窗口 导入文件&#xff0c;然后点击导入按钮。

2024第十五届蓝桥杯网络安全赛项WriteUp

欢迎关注公众号【Real返璞归真】回复【蓝桥杯2024】获取完整题目附件。 排名 安全知识 错1个选择题&#xff0c;题目说的不清楚&#xff0c;没搞懂题意。肯定不能用eval。错了理论题有点遗憾。 没想到这题前端是要解析json数据&#xff0c;排除CD选了A&#xff0c;结果发现正…

【Hadoop】-HDFS的存储原理[4]

目录 前言 一、fsck命令 1、HDFS副本块数量的配置 2、fsck命令查看文件的副本数 3、block配置 二、NameNode元数据 1、edits文件 2、fsigame文件 3、NameNode元数据管理维护 4、元数据合并控制参数 5、SecondaryNameNode的作用 三、HDFS数据的读写流程 1、数据写入…

软考之零碎片段记录(二十六)+复习巩固(十一、十二)

学习 1. 有向图邻接表中有奇数个表节点。无向图邻接表有偶数个 2. OSI模型 物理层->数据链路->网络->应用… 3. 无痕浏览 会被保存。下载的文件不会保存。浏览记录。Cookie和网站数据。表单中填写的信息。 4. 邮件收发协议 FTP不属于邮件收发协议 SMTP。简单邮…

python中如何用matplotlib写饼图

#代码 import matplotlib.pyplot as plt# 设置绘图的主题风格 plt.style.use(ggplot) # 中文乱码和坐标轴负号的处理 plt.rcParams[font.sans-serif][SimHei] plt.rcParams[axes.unicode_minus]False plt.rcParams[figure.figsize][10,8] # 构造数据 x [0.2515,0.3724,0.3336…

深入理解操作系统与计算机体系结构

文章目录 操作系统(Operator System)为什么要有操作系统操作系统是如何进行管理的为什么说操作系统是安全&#xff0c;稳定&#xff0c;高效的理解系统调用和库函数 操作系统(Operator System) 概念&#xff1a; 操作系统&#xff08;Operating System&#xff0c;简称OS&…

python自动化登录(测试篇)

起初是想抓取下请求看能不能做模拟登录。无奈发现&#xff0c;目标网站的请求数据是加密过的&#xff0c;而且网站代码也是编译后的代码。要从编译后的代码中提取加密算法。我的第一想法是明知不可为而不为。但是转念一想&#xff0c;何不试试python大法。 1.前期准备 python我…

WIFI加密方式对无线速率的影响

文章目录 无线加密三种选择&#xff1a;WEP、WPA和WPA2测试平台和测试方法非加密和WEP加密测试 结果差别巨大非加密条件下 300M无线路由实测WEP加密条件下 300M无线路由实测 TKIP加密算法&#xff1a;WPA与WPA2成绩低迷WPA加密&#xff08;TKIP加密算法&#xff09;条件下 300M…

万兆以太网MAC设计(6)IP协议报文格式详解以及IP层模块设计

文章目录 前言&#xff1a;IPv4报文协议格式二、IP_RX模块设计2.1、模块接口2.2、模块工作过程 三、IP_TX模块设计3.1、模块接口3.2、模块工作过程 四、仿真4.1、发送端4.2、接受端 前言&#xff1a;IPv4报文协议格式 参考&#xff1a;https://sunyunqiang.com/blog/ipv4_prot…

CLIP论文笔记:Learning Transferable Visual Models From Natural Language Supervision

导语 会议&#xff1a;ICML 2021链接&#xff1a;https://proceedings.mlr.press/v139/radford21a/radford21a.pdf 当前的计算机视觉系统通常只能识别预先设定的对象类别&#xff0c;这限制了它们的广泛应用。为了突破这一局限&#xff0c;本文探索了一种新的学习方法&#x…

[ESP32]:TFLite Micro推理CIFAR10模型

[ESP32]&#xff1a;TFLite Micro推理CIFAR10模型 模型训练 数据集处理 from keras.datasets import cifar10 from keras.preprocessing.image import ImageDataGenerator from keras.models import Sequential, load_model, Model from keras.layers import Input, Dense, …

SSH新功能揭秘:远程工作提升指南【AI写作】

首先&#xff0c;这篇文章是基于笔尖AI写作进行文章创作的&#xff0c;喜欢的宝子&#xff0c;也可以去体验下&#xff0c;解放双手&#xff0c;上班直接摸鱼~ 按照惯例&#xff0c;先介绍下这款笔尖AI写作&#xff0c;宝子也可以直接下滑跳过看正文~ 笔尖Ai写作&#xff1a;…
最新文章