Qt6替代废弃QMediaPlaylist的解决方案
作者:ol木子李lo
—— 之前使用Qt5,如今使用Qt6发现在Qt6里QMediaPlaylist已废弃,所以网上搜了一下,找到了该博主的博客,感想博主的代码,我在其基础上增加和修改,以适配Qt5的写法。
一、背景:Qt6 多媒体模块的重大变更
Qt5 中常用的 QMediaPlaylist 类在 Qt6 中被正式移除,这给大量依赖该类实现音频 / 视频播放列表管理的项目带来了兼容性问题。尤其对于棋牌、影音类应用(如本文的斗地主项目),播放列表是核心功能模块,急需一套轻量、兼容、易集成的替代方案。
本文基于实际项目经验,从零实现了一套 Qt6 专属的 MediaPlaylist 类,完全复刻 QMediaPlaylist 核心能力,同时适配 Qt6 新的多媒体架构(QMediaPlayer + QAudioOutput),解决音频播放列表、循环切歌、播放模式控制等核心需求。
二、核心痛点分析
迁移 Qt5 音频播放逻辑到 Qt6 时,主要面临以下问题:
QMediaPlaylist直接移除,无官方替代类;- Qt6 多媒体架构调整,
QMediaPlayer需手动绑定QAudioOutput,且播放状态监听逻辑变更; - 原有播放模式(单曲循环、列表循环、单次播放)需重新实现;
- 音频索引切换、自动切歌等核心逻辑需手动封装。
三、解决方案:自定义 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,实现两个核心能力:
- 自动监听
mediaStatusChanged信号,无需外部手动处理播放完成事件; - 切换索引时自动调用
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 多媒体架构,核心优势:
- 低改造成本:接口设计贴近 Qt5
QMediaPlaylist,项目迁移时无需大幅修改业务逻辑; - 高稳定性:完善的索引校验、内存管理,避免空指针 / 越界崩溃;
- 强扩展性:保留
currentIndexChanged信号,支持后续 UI 同步、日志记录等扩展; - 零依赖:仅依赖 Qt6 Core 和 Multimedia 模块,无需第三方库。
以上就是Qt6替代废弃QMediaPlaylist的解决方案的详细内容,更多关于Qt6替代废弃QMediaPlaylist的资料请关注脚本之家其它相关文章!
