C++客户端Qt开发——系统相关(多媒体音频)

news2025/1/16 0:53:34

3.多媒体(音频、视频)

播放声音需要引入multimedia模块

使用QSound

仅支持的音频文件格式为.wav,同样使用qrc文件管理外部的资源

(使用的.wav文件不宜过大,尽量在几秒内,否则会构建时间过长)

wav是一种无损格式,能够提供比其他格式更高质量的音频,wav文件的质量比较高,从而文件大小也相对会大一点

1>用按钮控制播放音频

.pro中导入multimedia模块:

#include "widget.h"
#include "ui_widget.h"
#include <QSound>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    //1.直接调用 QSound::play
    //QSound::play(":/eatfood.wav");

    //2.创建 QSound 实例并播放
    QSound* sound = new QSound(":/eatfood.wav",this);
    sound->play();

    //delete sound;
    //这里不能加delete,原因在下方说明
}

1. 直接调用QSound::play会不会导致内存泄漏

不会,QSound::play 是一个静态成员函数,直接调用它不会创建新的对象,因此也不需要担心内存释放的问题。由于它是静态成员函数,它是由类本身调用的,而不是某个对象,因此不涉及对象的内存管理问题。这个方法适用于播放短小的声音文件。

2. 为什么不能加delete,为什么加了delete后就播放不出声音了

实际上播放了,但是在听到音频之前就执行了delete,立即删除 QSound 对象时,声音播放的过程会被打断,因为 QSound 对象在播放声音的过程中需要存在。删除对象会终止声音播放,所以你会听不到声音。

3. 那不能加delete,这种手动创建的方式会导致内存泄漏吗

有可能, 如果你不删除 QSound 对象,确实可能会导致内存泄漏。每次点击按钮都会创建一个新的 QSound 对象,如果不释放这些对象,内存会不断增长,最终可能会耗尽内存。

4. 针对第三问如何解决

使用事件循环解决内存泄漏问题,第六点的第④种方法

可以使用 QObject 的事件机制来在声音播放结束时自动删除 QSound 对象。具体可以通过连接 QSoundfinished 信号到一个槽函数,在槽函数中删除 QSound 对象。

示例代码如下:

void Widget::on_pushButton_clicked()
{
    QSound* sound = new QSound(":/eatfood.wav", this);
    connect(sound, &QSound::finished, sound, &QObject::deleteLater);
    sound->play();
}
//deleteLater 方法会在事件循环的下一个空闲时刻自动删除 sound 对象。
//这种方法可以确保声音播放完成后再删除对象,从而避免内存泄漏和播放被中断的问题。

5. 事件循环的原理

  • 事件循环 (event loop) 是 GUI 应用程序的核心机制之一,用于管理和分发事件。
  • Qt 的事件循环(QCoreApplication::execQApplication::exec)主要负责处理用户输入、定时器、网络事件等。它不直接管理 QSound 对象的释放。
  • Qt 的事件循环是通过 QCoreApplication 或其子类(如 QApplication)实现的。
  • 当一个事件(如信号发射)发生时,事件循环会将事件放入事件队列中,并在适当的时候处理这些事件。deleteLater 方法将删除操作推迟到事件循环的下一次空闲时刻,这样可以确保对象在安全的时刻被删除。

6. 其他解决办法

① 使用智能指针(如 std::unique_ptrstd::shared_ptr

智能指针可以自动管理对象的生命周期,当智能指针超出作用域时,它会自动删除所指向的对象。这种方法简单,但需要确保对象在播放完成之前不会超出作用域。

② 手动管理对象的生命周期

你可以创建一个成员函数或使用 Qt 的定时器来延迟删除 QSound 对象。

③ 使用 QTimer 延迟删除

通过 QTimer 设置一个定时器,在声音播放结束后删除 QSound 对象。可以根据声音文件的长度调整定时器的时间。

④ 使用 QEventLoop

在需要的情况下,你可以手动创建一个 QEventLoop 来等待声音播放完成。QEventLoop 在声音播放完成前一直运行,确保 QSound 对象在播放完成后才销毁。

⑤ 将 QSound 作为成员变量

如果你希望反复使用同一个 QSound 对象,可以将它作为类的成员变量。这种方法避免了反复创建和删除对象,但需要注意对象的重用。通过将 QSound 作为成员变量,你只需创建一次对象,并在需要时播放声音。

2>使用第六种解决方法解决上题
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QSound>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private slots:
    void on_pushButton_clicked();

private:
    Ui::Widget *ui;
    QSound* sound;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"


Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    sound = new QSound(":/eatfood.wav",this);
}

Widget::~Widget()
{
    delete ui;
}


void Widget::on_pushButton_clicked()
{
    sound->play();
}
  • 对象持久化: 通过将 QSound 对象作为类的成员变量,可以确保对象在整个类的生命周期内都存在,不会在每次使用时创建和销毁。这减少了对象的创建和销毁开销。
  • 内存管理: 通过在构造函数中创建对象,并在析构函数中删除对象,可以确保在对象不再需要时正确释放内存,从而避免内存泄漏。
  • 父子对象机制: 在创建 QSound 对象时,我们将 Widget 对象设为其父对象。这意味着当 Widget 对象销毁时,Qt 会自动销毁其所有子对象,包括 QSound 对象。这进一步简化了内存管理。

优缺点

  • 优点:

①避免了频繁创建和销毁对象的开销。

②简化了内存管理,减少了内存泄漏的风险。

③使用父子对象机制,使对象的生命周期与父对象同步。

  • 缺点:

①如果需要播放不同的声音文件,必须重新创建或重新配置 QSound 对象。

②如果 Widget 对象生命周期较长,而声音播放不频繁,可能会占用一些不必要的内存。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

拓维思树障分析Tovos PowerLine 4.0.19 航线规划Tovos SmartPlan 2.0.0 下载License电力应用软件使用

Tovos PowerLine 是功能强大的输电线路智能巡检系统&#xff01;这是一个专业且智能的软件&#xff0c;能够更准确的进行巡检和对线路设备进行精确的测量&#xff0c;通过获取高精度的点云来获取精准的三维路线的地形地貌、设备设施、途径的各种物体等来精确您的三维空间信息和…

三子棋小程序

一.自定义头文件(game.h) 放入源文件需要用到的标准库头文件和函数的声明 ROW 和COL为棋盘的行和列&#xff0c;三子棋嘛&#xff0c;肯定为3啦 #pragma once #include<stdio.h> #include<String.h> #include<stdlib.h> #include<time.h> #define ROW…

中国少女徐可昕心怀爱豆梦 为实现梦想勇赴韩国

如今MZ世代(MZ世代是‌Millennial世代和‌Z世代的合成词,用来描述1980至2000年间出生的人)小伙伴们追求着怎样的梦想呢?随着韩国K-POP热潮和娱乐产业的发展,越来越多的年轻人希望可以在娱乐圈工作,例如成为爱豆或经理人。通过抖音或YouTube等,可以发现很多才华横溢的年轻人创作…

malloc 对比验证 posix_memalign 的功能

1&#xff0c;函数说明 posix_memalign 是一个 POSIX 标准定义的函数&#xff0c;用于在内存中分配对齐的内存块。这个函数可以确保分配的内存块满足特定的对齐要求&#xff0c;通常用于需要对齐内存访问的情况&#xff0c;比如 SIMD 指令集的使用或者特定硬件要求的内存对齐。…

瑞派明星医生:技术深耕教学指导,燃动当代名校兽医双效技能Buff

名校精进&#xff0c;攻破技术堡垒 从动物保护、环境保护的最初理想&#xff0c;到兽医学专业领域深耕&#xff0c;天津瑞派长江宠物医院的唐玉洁医生正用自己的实际行动展现着当代兽医人才背后的奉献、良知、超越与传承。 享受了东北林业大学带来的短暂而有趣的大学生活&…

聊聊RNN与Attention

前言 Attention Mechanism&#xff0c;称为注意力机制。基于Attention机制&#xff0c;seq2seq可以像我们人类一样&#xff0c;将“注意力”集中在必要的信息上。 Attention的结构 seq2seq存在的问题 seq2seq中使用编码器对时序数据进行编码&#xff0c;然后将编码信息传递…

JS:JavaScript 简介

前言 在当今数字时代&#xff0c;JavaScript已然成为了现代Web开发的基石。从最初作为浏览器中的一个小型脚本语言&#xff0c;到如今成为驱动全球互联网的强大引擎&#xff0c;JavaScript的发展历程本身就是一个令人着迷的故事。 好了开始学习JS吧 1. 如果刚开始了解js&#…

Node.js自动化处理TOML文件

在软件开发过程中&#xff0c;自动化处理配置文件是一种常见的需求。TOML&#xff08;Tom’s Obvious, Minimal Language&#xff09;是一种用于配置文件的简单易读的格式。本文将展示如何使用Node.js和一些流行的库来自动化读取、修改并写入TOML文件。 1. 准备工作 在开始之前…

IAR工程设置

这篇记录一下工作中对IARide的工程设置的配置步骤。 所以这不是一篇通用的文章&#xff0c;只是个人记录。 目的&#xff1a;为了是ARM仿真器能够下载调试锐能微的芯片 一、工程设置 1、更改boot文件的工程设置&#xff1a; 2、编译boot文件 3、配置8213B的工程设置&#x…

iPhone 16 Pro Max电池大揭秘,听说迎来了有史以来最持久的续航

智能手机市场的竞争日益激烈&#xff0c;各大厂商都在寻求创新以保持领先地位。而苹果公司即将推出的iPhone 16 Pro Max&#xff0c;则以其革命性的不锈钢电池壳和电诱导粘合剂脱离技术&#xff0c;再次刷新了我们对智能手机电池技术的认知。 一、不锈钢电池壳的突破 苹果公司…

Windows系统编程API 学习之路

目录 I. 基础 进程 动态链接库 线程 Windows应用程序开发 初入Windows编程 使用strings C/C运行时中的字符串 安全字符串函数 32位与64位开发 定义自定义错误代码 I. 基础 Windows NT操作系统系列有着悠久的历史&#xff0c;从1993年推出的3.1版本开始。今天的Windo…

如何主持收集故事研讨会

如何主持收集故事研讨会 引言 在文化的长河中,故事是传承知识、情感与智慧的桥梁。收集故事不仅是对过去的回顾,更是对未来灵感的启迪。组织一场收集故事研讨会,旨在汇聚各界人士,共同挖掘、整理并分享那些触动人心、富有意义的故事。作为这样一场活动的主持人,您的角色…

C++开源界面库duilib的使用细节与实战技巧总结(实战经验分享)

目录 1、使用CEditUI编辑框 2、使用CLabelUI或CTextUI的Html文本效果 3、使用CTextUI控件对文字宽度自适应的特性 4、CRichEditUI富文本控件使用注意点 4.1、指定CRichEditUI加在2.0版本的Riched20.dll库 4.2、解决向CRichEditUI中插入文字后显示空白的问题 5、设置窗口…

拓扑排序+dp(消除主观臆断)

这题一开始写错的原因就是搞错了&#xff0c;处于西边的节点的编号不一定小&#xff0c;不能直接dp&#xff0c;要先进行拓扑排序 写到一般我才发现&#xff0c;其实可以一边dp&#xff0c;一边进行dp #define _CRT_SECURE_NO_WARNINGS #include<bits/stdc.h> using name…

信息安全工程师下午题

试题一(共 20 分) 阅读下列说明和图&#xff0c;回答问题 1 至问题 5&#xff0c;将解答填入答题纸的对应栏内。【说明】已知某公司网络环境结构主要由三个部分组成&#xff0c;分别是 DMZ 区、内网办公区和生产区&#xff0c;其拓扑结构如图 1-1 所示。信息安全部的王工正在按…

无人机像素经纬度识别

&#x1f3c6;本文收录于《CSDN问答解惑-专业版》专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收…

代码随想录——组合总和 Ⅳ(Leetcode377)

题目链接 动态规划 class Solution {public int combinationSum4(int[] nums, int target) {int[] dp new int[target 1];dp[0] 1;for(int i 0; i < target; i){for(int j 0; j < nums.length; j){if(i > nums[j]){dp[i] dp[i - nums[j]];} }}return dp[targ…

【原创】java+ssm+mysql医生信息管理系统设计与实现

个人主页&#xff1a;程序员杨工 个人简介&#xff1a;从事软件开发多年&#xff0c;前后端均有涉猎&#xff0c;具有丰富的开发经验 博客内容&#xff1a;全栈开发&#xff0c;分享Java、Python、Php、小程序、前后端、数据库经验和实战 开发背景&#xff1a; 随着信息技术的…

【Golang 面试 - 基础题】每日 5 题(七)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/UWz06 &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏…

ajax请求成功但不执行success-function回调函数

目录 一、问题分析 二、处理问题 一、问题分析 在测试员工管理系统的登录和注册代码时&#xff0c;登录一切正常&#xff0c;就是注册成功后没有跳转页面&#xff0c;后面发现是success-function回调函数没有正常执行。原因主要是前端和后端交流的数据格式不一致&#xff0c;…