Qt6替代废弃QMediaPlaylist的解决方案

 更新时间:2026年04月16日 09:11:21   作者:ol木子李lo  
本文介绍了一种自定义的Qt6多媒体播放列表类,以兼容Qt6的新多媒体架构,该类支持三种播放模式,并自动绑定QMediaPlayer,实现了自动切换媒体的功能,作者还提供了代码实现,并通过实际项目中的BGMControl类进行了集成示例,需要的朋友可以参考下

—— 之前使用Qt5,如今使用Qt6发现在Qt6里QMediaPlaylist已废弃,所以网上搜了一下,找到了该博主的博客,感想博主的代码,我在其基础上增加和修改,以适配Qt5的写法。

一、背景:Qt6 多媒体模块的重大变更

Qt5 中常用的 QMediaPlaylist 类在 Qt6 中被正式移除,这给大量依赖该类实现音频 / 视频播放列表管理的项目带来了兼容性问题。尤其对于棋牌、影音类应用(如本文的斗地主项目),播放列表是核心功能模块,急需一套轻量、兼容、易集成的替代方案。

本文基于实际项目经验,从零实现了一套 Qt6 专属的 MediaPlaylist 类,完全复刻 QMediaPlaylist 核心能力,同时适配 Qt6 新的多媒体架构(QMediaPlayer + QAudioOutput),解决音频播放列表、循环切歌、播放模式控制等核心需求。

二、核心痛点分析

迁移 Qt5 音频播放逻辑到 Qt6 时,主要面临以下问题:

  1. QMediaPlaylist 直接移除,无官方替代类;
  2. Qt6 多媒体架构调整,QMediaPlayer 需手动绑定 QAudioOutput,且播放状态监听逻辑变更;
  3. 原有播放模式(单曲循环、列表循环、单次播放)需重新实现;
  4. 音频索引切换、自动切歌等核心逻辑需手动封装。

三、解决方案:自定义 MediaPlaylist 类实现

3.1 类设计思路

遵循 Qt 信号槽设计规范,封装播放列表核心能力,核心设计目标:

  • 兼容 Qt6 QMediaPlayer 新架构;
  • 支持三种经典播放模式;
  • 自动监听播放完成状态,实现无感切歌;
  • 提供简洁的外部接口,最小化项目改造成本。

3.2 完整代码实现

  • 头文件(ol_MediaPlaylist.h)
/****************************************************************************************/
/*
 * 程序名:ol_MediaPlaylist.h
 * 功能描述:Qt6 媒体播放列表类,替代废弃的 QMediaPlaylist,支持以下特性:
 *          - 自动绑定 QMediaPlayer,监听播放完成状态
 *          - 三种播放模式:单次播放、单曲循环、列表循环
 *          - 播放结束自动切换曲目/循环播放
 *          - 索引/媒体资源自动管理,适配 Qt6
 *          - 支持信号通知索引变化,与音频播放器联动
 * 作者:ol
 * 适用标准:Qt 6.0及以上
 */
/****************************************************************************************/
#ifndef OL_MEDIAPLAYLIST_H
#define OL_MEDIAPLAYLIST_H
#include <QObject>
#include <QVector>
#include <QUrl>
#include <QMediaPlayer>
namespace ol
{
    /**
     * @brief 媒体播放列表类,适配 Qt6 QMediaPlayer
     * 实现播放列表管理、自动循环切歌、播放模式控制,无需手动处理音源切换
     */
    class MediaPlaylist : public QObject
    {
        Q_OBJECT
    public:
        /**
         * @brief 播放模式枚举
         */
        enum class PlaybackMode : char
        {
            CurrentItemOnce, /**< 当前曲目播放一次后自动停止 */
            CurrentItemLoop, /**< 当前曲目无限循环播放 */
            SequentialLoop   /**< 列表顺序循环,尾首自动衔接 */
        };
    private:
        QVector<QUrl> m_mediaList;   ///< 媒体资源 URL 列表
        int m_currentIndex;          ///< 当前播放索引,-1 表示未选中
        PlaybackMode m_playbackMode; ///< 当前播放模式
        QMediaPlayer* m_player;      ///< 绑定的 Qt 媒体播放器
    public:
        /**
         * @brief 构造函数
         * @param parent 父对象
         */
        explicit MediaPlaylist(QObject* parent = nullptr);
        /**
         * @brief 向播放列表添加媒体资源
         * @param media 媒体资源 URL(支持 qrc 资源/本地文件)
         */
        void addMedia(const QUrl& media);
        /**
         * @brief 清空播放列表,重置索引
         */
        void clear();
        /**
         * @brief 设置当前播放索引(自动切换播放器音源)
         * @param index 目标播放索引
         */
        void setCurrentIndex(int index);
        /**
         * @brief 获取当前播放索引
         * @return 当前索引,-1 表示无效
         */
        inline int getCurrentIndex() const { return m_currentIndex; }
        /**
         * @brief 获取当前播放的媒体 URL
         * @return 有效 URL / 空 QUrl
         */
        QUrl getCurrentMedia() const;
        /**
         * @brief 获取列表总媒体数量
         * @return 媒体资源总数
         */
        inline qsizetype getMediaCount() const { return m_mediaList.size(); }
        /**
         * @brief 设置播放模式
         * @param mode 目标播放模式
         */
        inline void setPlaybackMode(PlaybackMode mode) { m_playbackMode = mode; }
        /**
         * @brief 获取当前播放模式
         * @return 播放模式枚举值
         */
        inline PlaybackMode getPlaybackMode() const { return m_playbackMode; }
        /**
         * @brief 绑定 Qt 媒体播放器
         * @param player 待绑定的 QMediaPlayer 对象
         */
        void setPlayer(QMediaPlayer* player);
        /**
         * @brief 切换到下一首媒体
         * @return 下一首媒体的 URL
         */
        QUrl nextMedia();
        /**
         * @brief 切换到上一首媒体
         * @return 上一首媒体的 URL
         */
        QUrl previousMedia();
    signals:
        /**
         * @brief 播放索引改变信号,用于用户未来功能扩展
         * @param newIndex 新的播放索引
         */
        void currentIndexChanged(int newIndex);
    private slots:
        /**
         * @brief 监听播放器状态,播放完成自动处理切歌/循环
         * @param status 媒体播放状态
         */
        void onMediaStatusChanged(QMediaPlayer::MediaStatus status);
    };
} // namespace ol
#endif // !OL_MEDIAPLAYLIST_H
  • 源文件(ol_MediaPlaylist.cpp)
/****************************************************************************************/
/*
 * 程序名:ol_MediaPlaylist.cpp
 * 功能描述:媒体播放列表类实现文件
 * 作者:ol
 */
/****************************************************************************************/
#include "ol_MediaPlaylist.h"
#include <QMediaPlayer>

namespace ol
{
    MediaPlaylist::MediaPlaylist(QObject* parent)
        : QObject(parent), m_currentIndex(-1), m_playbackMode(PlaybackMode::CurrentItemOnce), m_player(nullptr)
    {
    }

    void MediaPlaylist::addMedia(const QUrl& media)
    {
        m_mediaList.append(media);
        if (m_currentIndex == -1) setCurrentIndex(0);
    }

    void MediaPlaylist::clear()
    {
        m_mediaList.clear();
        m_currentIndex = -1;
        emit currentIndexChanged(m_currentIndex);
    }

    void MediaPlaylist::setCurrentIndex(int index)
    {
        if (index >= 0 && index < m_mediaList.size() && index != m_currentIndex)
        {
            m_currentIndex = index;
            emit currentIndexChanged(m_currentIndex);

            // 自动切换播放器音源
            if (m_player) m_player->setSource(getCurrentMedia());
        }
    }

    QUrl MediaPlaylist::getCurrentMedia() const
    {
        if (m_currentIndex >= 0 && m_currentIndex < m_mediaList.size()) return m_mediaList.at(m_currentIndex);
        return QUrl();
    }

    void MediaPlaylist::setPlayer(QMediaPlayer* player)
    {
        // 断开旧播放器连接
        if (m_player) disconnect(m_player, nullptr, this, nullptr);

        m_player = player;

        // 绑定状态监听信号
        if (m_player)
        {
            connect(m_player, &QMediaPlayer::mediaStatusChanged, this, &MediaPlaylist::onMediaStatusChanged);

            // 默认加载当前音源
            const QUrl url = getCurrentMedia();
            if (url.isValid()) m_player->setSource(url);
        }
    }

    QUrl MediaPlaylist::nextMedia()
    {
        if (m_mediaList.isEmpty()) return QUrl();

        setCurrentIndex((m_currentIndex + 1) % m_mediaList.size());
        return getCurrentMedia();
    }

    QUrl MediaPlaylist::previousMedia()
    {
        if (m_mediaList.isEmpty()) return QUrl();

        setCurrentIndex((m_currentIndex - 1 + m_mediaList.size()) % m_mediaList.size());
        return getCurrentMedia();
    }

    void MediaPlaylist::onMediaStatusChanged(QMediaPlayer::MediaStatus status)
    {
        // 仅处理播放完成状态
        if (status != QMediaPlayer::EndOfMedia || !m_player) return;
        if (m_mediaList.isEmpty()) return;

        switch (m_playbackMode)
        {
        case PlaybackMode::CurrentItemOnce:
            m_player->stop();
            break;
        case PlaybackMode::CurrentItemLoop:
            m_player->play();
            break;
        case PlaybackMode::SequentialLoop:
            nextMedia();
            m_player->play();
            break;
        }
    }

} // namespace ol

四、核心功能解析

4.1 播放模式控制

复刻 Qt5 QMediaPlaylist 三种经典模式,通过 PlaybackMode 枚举实现:

  • CurrentItemOnce:播放完成后自动停止;
  • CurrentItemLoop:单曲无限循环(播放完成后重新播放);
  • SequentialLoop:列表循环(播放完成自动切下一首,最后一首切回第一首)。

4.2 自动绑定播放器

通过 setPlayer 方法绑定 QMediaPlayer,实现两个核心能力:

  1. 自动监听 mediaStatusChanged 信号,无需外部手动处理播放完成事件;
  2. 切换索引时自动调用 setSource,避免外部重复编写音源切换逻辑。

4.3 索引安全管理

所有索引操作(setCurrentIndex/nextMedia/previousMedia)均做合法性校验:

  • 索引越界时不执行任何操作;
  • 空列表时返回空 URL,避免程序崩溃;
  • 首次添加媒体自动选中第一个索引,降低使用成本。

五、项目集成示例

以实际项目中的 BGMControl 类为例,展示如何快速集成自定义 MediaPlaylist

// 音频控制类中初始化播放列表
BGMControl::BGMControl(QObject* parent) : QObject(parent)
{
    // 初始化5组音频单元(男女音效/BGM/辅助音效/结束音效)
    for (int i = 0; i < 5; ++i)
    {
        QAudioOutput* output = new QAudioOutput(this);
        QMediaPlayer* player = new QMediaPlayer(this);
        ol::MediaPlaylist* playlist = new ol::MediaPlaylist(this);

        // 绑定播放器与播放列表
        player->setAudioOutput(output);
        playlist->setPlayer(player);
        output->setVolume(1.0f);

        // 配置播放模式(BGM列表循环,其他单次播放)
        if (i == 2) {
            playlist->setPlaybackMode(ol::MediaPlaylist::PlaybackMode::SequentialLoop);
        } else {
            playlist->setPlaybackMode(ol::MediaPlaylist::PlaybackMode::CurrentItemOnce);
        }

        m_outputs.push_back(output);
        m_players.push_back(player);
        m_playlists.push_back(playlist);
    }

    // 加载音频资源
    initPlayList();
}

// 启动BGM示例
void BGMControl::startBGM(float volume)
{
    m_outputs[2]->setVolume(volume);
    m_playlists[2]->setCurrentIndex(0); // 选中第一个BGM
    m_players[2]->play();               // 开始播放
}

六、总结

本文实现的 MediaPlaylist 类完全适配 Qt6 多媒体架构,核心优势:

  1. 低改造成本:接口设计贴近 Qt5 QMediaPlaylist,项目迁移时无需大幅修改业务逻辑;
  2. 高稳定性:完善的索引校验、内存管理,避免空指针 / 越界崩溃;
  3. 强扩展性:保留 currentIndexChanged 信号,支持后续 UI 同步、日志记录等扩展;
  4. 零依赖:仅依赖 Qt6 Core 和 Multimedia 模块,无需第三方库。

以上就是Qt6替代废弃QMediaPlaylist的解决方案的详细内容,更多关于Qt6替代废弃QMediaPlaylist的资料请关注脚本之家其它相关文章!

相关文章

  • C++基于EasyX库实现拼图小游戏

    C++基于EasyX库实现拼图小游戏

    这篇文章主要为大家详细介绍了C++基于EasyX库实现拼图小游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-07-07
  • C/C++实现通讯录管理系统(附源码)

    C/C++实现通讯录管理系统(附源码)

    这篇文章主要为大家详细介绍了如何利用C++实现通讯录管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-12-12
  • C语言实例之双向链表增删改查

    C语言实例之双向链表增删改查

    双向链表(Doubly Linked List)是一种常见的数据结构,在单链表的基础上增加了向前遍历的功能,与单向链表不同,双向链表的每个节点除了包含指向下一个节点的指针外,还包含指向前一个节点的指针,本文给大家介绍了C语言中双向链表的增删改查
    2023-08-08
  • C++容器算法示例详解

    C++容器算法示例详解

    在谈到容器算法,我们大概率会用到谓词predicate,谓词返回的类型是布尔类型(bool)可以是lambda表达式、函数对象以及其它可调用的对象,这篇文章主要介绍了C++容器算法,需要的朋友可以参考下
    2024-08-08
  • 一文详解C语言中文件相关函数的使用

    一文详解C语言中文件相关函数的使用

    这篇文章主要为大家详细介绍了C语言中文件相关函数的使用,可以实现文件的读写、打开和关闭。文中通过示例进行了详细介绍,需要的可以参考一下
    2022-07-07
  • C语言深入探究直接插入排序与希尔排序使用案例讲解

    C语言深入探究直接插入排序与希尔排序使用案例讲解

    算法中排序是十分重要的,而每一个学习计算机的都会在初期的时候接触到这种排序,下面这篇文章主要给大家介绍了关于c语言直接插入排序与希尔排序使用的相关资料,需要的朋友可以参考下
    2022-05-05
  • OpenCV实现给图片添加边框功能

    OpenCV实现给图片添加边框功能

    这篇文章主要为大家详细介绍了OpenCV实现给图片添加边框功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-10-10
  • C++ Boost Variant示例超详细讲解

    C++ Boost Variant示例超详细讲解

    Boost是为C++语言标准库提供扩展的一些C++程序库的总称。Boost库是一个可移植、提供源代码的C++库,作为标准库的后备,是C++标准化进程的开发引擎之一,是为C++语言标准库提供扩展的一些C++程序库的总称
    2022-11-11
  • C++链式二叉树深入分析

    C++链式二叉树深入分析

    二叉树的链式存储结构是指,用链表来表示一棵二叉树,即用链来指示元素的逻辑关系。通常的方法是链表中每个结点由三个域组成,数据域和左右指针域,左右指针分别用来给出该结点左孩子和右孩子所在的链结点的存储地址
    2022-06-06
  • C语言实现bmp图像对比度扩展

    C语言实现bmp图像对比度扩展

    这篇文章主要为大家详细介绍了C语言实现bmp图像对比度扩展,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-10-10

最新评论