Qt QMediaPlayer 类与 QMediaPlaylist 类
Qt Multimedia 模块音频播放核心:媒体播放器 + 播放列表实战手册

目录
文章目录
- [Qt QMediaPlayer 类与 QMediaPlaylist 类](#Qt QMediaPlayer 类与 QMediaPlaylist 类)
-
- 目录
- [1. Qt 音频基础知识](#1. Qt 音频基础知识)
-
- [1.1 引入多媒体模块](#1.1 引入多媒体模块)
- [1.2 核心类介绍](#1.2 核心类介绍)
- [1.3 两者关系](#1.3 两者关系)
- [2. QMediaPlayer 类常用 API](#2. QMediaPlayer 类常用 API)
-
- [2.1 基本操作(播放 / 暂停 / 停止)](#2.1 基本操作(播放 / 暂停 / 停止))
- [2.2 音量控制](#2.2 音量控制)
- [2.3 播放进度控制](#2.3 播放进度控制)
- [2.4 状态与错误](#2.4 状态与错误)
- [2.5 常用信号](#2.5 常用信号)
- [3. QMediaPlaylist 类常用 API](#3. QMediaPlaylist 类常用 API)
-
- [3.1 创建与绑定播放器](#3.1 创建与绑定播放器)
- [3.2 添加 / 移除媒体条目](#3.2 添加 / 移除媒体条目)
- [3.3 播放控制](#3.3 播放控制)
- [3.4 播放模式(重中之重)](#3.4 播放模式(重中之重))
- [3.5 常用信号](#3.5 常用信号)
- [4. 完整实战:简易音乐播放器](#4. 完整实战:简易音乐播放器)
-
- [4.1 项目文件(.pro)](#4.1 项目文件(.pro))
- [4.2 音乐播放器核心逻辑](#4.2 音乐播放器核心逻辑)
- 效果
- [4.3 界面版补充要点](#4.3 界面版补充要点)
- [6. 常见坑与 FAQ](#6. 常见坑与 FAQ)
-
- [6.1 没有声音 / 提示没有音频输出(Qt 6 专属)](#6.1 没有声音 / 提示没有音频输出(Qt 6 专属))
- [6.2 播放不了 MP3 等格式](#6.2 播放不了 MP3 等格式)
- [6.3 进度条不居中 / 位置异常](#6.3 进度条不居中 / 位置异常)
- [6.4 `previous()` 行为不符合预期](#6.4
previous()行为不符合预期) - [6.5 播放列表如何自动连续播放](#6.5 播放列表如何自动连续播放)
- [6.6 网络收音机 / 流媒体播放](#6.6 网络收音机 / 流媒体播放)
- 快速参考表
1. Qt 音频基础知识
1.1 引入多媒体模块
使用音频功能前,需要在 .pro 项目文件中添加多媒体模块:
cpp
QT += multimedia
Qt 6 中,
QMediaPlayer与QMediaPlaylist属于Qt Multimedia模块,同样使用QT += multimedia。
1.2 核心类介绍
- QMediaPlayer:媒体播放器,主要用于播放歌曲、网络收音机、视频等功能。它封装了底层音视频解码与播放引擎,提供播放/暂停/停止/定位等操作接口。
- QMediaPlaylist :专用于播放媒体内容的列表。可以维护一组媒体条目,支持顺序播放、随机播放、循环播放,并能与
QMediaPlayer绑定实现"播放器 + 歌单"的完整播放体验。
1.3 两者关系
QMediaPlaylist(歌单) ──绑定──> QMediaPlayer(播放器) ──输出──> 扬声器/屏幕
│
└── 保存多个 QMediaContent / QUrl
QMediaPlaylist 负责"播什么、按什么顺序播",QMediaPlayer 负责"怎么播出来"。二者通过 player->setPlaylist(playlist) 联动。
2. QMediaPlayer 类常用 API
2.1 基本操作(播放 / 暂停 / 停止)
cpp
QMediaPlayer *player = new QMediaPlayer(this);
player->setMedia(QUrl::fromLocalFile("D:/music/1.mp3")); // 设置媒体
player->play(); // 播放
player->pause(); // 暂停
player->stop(); // 停止(回到开头)
| 接口 | 说明 |
|---|---|
setMedia(const QMediaContent &) |
设置要播放的媒体内容 |
play() |
开始/恢复播放 |
pause() |
暂停播放 |
stop() |
停止播放并复位到开头 |
2.2 音量控制
cpp
player->setVolume(50); // 设置音量 0 ~ 100
int v = player->volume(); // 获取当前音量
player->setMuted(true); // 静音
bool m = player->isMuted();
| 接口 | 说明 |
|---|---|
setVolume(int) |
设置音量(0~100,Qt 6 为线性 0.0~1.0 见差异) |
volume() |
获取当前音量 |
setMuted(bool) |
静音开关 |
isMuted() |
是否静音 |
2.3 播放进度控制
cpp
player->setPosition(30000); // 跳到 30 秒处(毫秒)
qint64 pos = player->position(); // 当前播放位置(毫秒)
qint64 dur = player->duration(); // 媒体总时长(毫秒)
bool avail = player->isSeekable(); // 是否可定位
| 接口 | 说明 |
|---|---|
setPosition(qint64) |
设置播放位置(毫秒) |
position() |
当前播放位置 |
duration() |
媒体总时长(-1 表示未知) |
isSeekable() |
是否支持定位 |
2.4 状态与错误
cpp
QMediaPlayer::State state = player->state(); // 播放状态
QMediaPlayer::MediaStatus status = player->mediaStatus(); // 媒体加载状态
QMediaPlayer::Error err = player->error(); // 错误码
QString errStr = player->errorString(); // 错误描述
State 枚举(播放状态):
| 值 | 说明 |
|---|---|
StoppedState |
停止 |
PlayingState |
播放中 |
PausedState |
已暂停 |
MediaStatus 枚举(媒体状态):
| 值 | 说明 |
|---|---|
NoMedia |
未设置媒体 |
LoadingMedia |
正在加载 |
LoadedMedia |
已加载 |
BufferingMedia |
缓冲中 |
BufferedMedia |
缓冲完成 |
EndOfMedia |
播放到结尾 |
InvalidMedia |
媒体无效(无法播放) |
2.5 常用信号
cpp
connect(player, &QMediaPlayer::positionChanged, this, [=](qint64 pos){
ui->slider->setValue(pos); // 更新进度条
});
connect(player, &QMediaPlayer::durationChanged, this, [=](qint64 dur){
ui->slider->setMaximum(dur); // 设置进度条最大值
});
connect(player, &QMediaPlayer::stateChanged, this, [=](QMediaPlayer::State s){
if (s == QMediaPlayer::PlayingState)
ui->btnPlay->setText("暂停");
else
ui->btnPlay->setText("播放");
});
connect(player, &QMediaPlayer::mediaStatusChanged, this, [=](QMediaPlayer::MediaStatus s){
if (s == QMediaPlayer::EndOfMedia)
; // 单曲播放结束处理
});
| 信号 | 触发时机 |
|---|---|
positionChanged(qint64) |
播放位置变化 |
durationChanged(qint64) |
时长已知/变化 |
stateChanged(State) |
播放状态变化 |
volumeChanged(int) |
音量变化 |
mutedChanged(bool) |
静音状态变化 |
mediaStatusChanged(MediaStatus) |
媒体加载状态变化 |
error(QMediaPlayer::Error) |
发生错误 |
3. QMediaPlaylist 类常用 API
3.1 创建与绑定播放器
cpp
QMediaPlaylist *playlist = new QMediaPlaylist(this);
QMediaPlayer *player = new QMediaPlayer(this);
player->setPlaylist(playlist); // 将歌单绑定到播放器
player->setVolume(60);
player->play();
绑定后,播放器播放的将是歌单中的内容,无需再单独
setMedia()。
3.2 添加 / 移除媒体条目
cpp
playlist->addMedia(QUrl::fromLocalFile("D:/music/1.mp3")); // 添加单个
playlist->addMedia(QUrl::fromLocalFile("D:/music/2.mp3"));
// 批量添加
QList<QMediaContent> list;
for (QString &f : files)
list << QMediaContent(QUrl::fromLocalFile(f));
playlist->addMedia(list);
// 在指定位置插入 / 移除
playlist->insertMedia(0, QMediaContent(QUrl::fromLocalFile("x.mp3")));
playlist->removeMedia(0); // 移除下标 0 的条目
playlist->clear(); // 清空歌单
| 接口 | 说明 |
|---|---|
addMedia(const QMediaContent &) |
末尾添加单条 |
addMedia(const QList<QMediaContent> &) |
批量添加 |
insertMedia(int, const QMediaContent &) |
指定位置插入 |
removeMedia(int) |
移除指定下标条目 |
clear() |
清空全部 |
mediaCount() |
条目数量 |
3.3 播放控制
cpp
playlist->next(); // 下一首
playlist->previous(); // 上一首
playlist->setCurrentIndex(2); // 跳到第 3 首
int idx = playlist->currentIndex(); // 当前曲目下标
QMediaContent cur = playlist->currentMedia(); // 当前媒体
| 接口 | 说明 |
|---|---|
next() |
跳到下一首(受播放模式影响) |
previous() |
跳到上一首 |
setCurrentIndex(int) |
跳到指定下标 |
currentIndex() |
当前下标 |
currentMedia() |
当前媒体内容 |
3.4 播放模式(重中之重)
cpp
playlist->setPlaybackMode(QMediaPlaylist::Loop); // 列表循环
playlist->setPlaybackMode(QMediaPlaylist::Random); // 随机播放
playlist->setPlaybackMode(QMediaPlaylist::Sequential); // 顺序播放(默认)
playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop); // 单曲循环
PlaybackMode 枚举:
| 值 | 说明 |
|---|---|
CurrentItemOnce |
当前曲目播放一次即停 |
CurrentItemInLoop |
单曲循环 |
Sequential |
顺序播放(放完即停) |
Loop |
列表循环 |
Random |
随机播放 |
3.5 常用信号
cpp
connect(playlist, &QMediaPlaylist::currentIndexChanged, this, [=](int i){
ui->labelSongName->setText(...); // 切换曲目时更新界面
});
connect(playlist, &QMediaPlaylist::mediaCountChanged, this, [=](int c){
; // 歌单数量变化
});
| 信号 | 触发时机 |
|---|---|
currentIndexChanged(int) |
当前曲目下标变化 |
currentMediaChanged(const QMediaContent &) |
当前媒体变化 |
mediaCountChanged(int) |
歌单数量变化 |
playbackModeChanged(PlaybackMode) |
播放模式变化 |
4. 完整实战:简易音乐播放器
一个可直接运行的控制台/界面最小示例,演示"歌单 + 播放器"联动。
4.1 项目文件(.pro)
cpp
QT += core gui multimedia
4.2 音乐播放器核心逻辑
cpp
// ================================================================
// QAudioFrePro.cpp
// Mp3 音频播放器主窗口的实现文件
// 负责:播放器/播放列表的创建与信号槽连接、歌曲加载与播放控制、
// 音量控制、进度显示与跳转、双击列表选歌等交互逻辑
// ================================================================
#include "QAudioFrePro.h"
// ---- Qt 核心/工具类 ----
// QDebug:调试输出(qDebug()),排查问题时使用
#include <QDebug>
// QDir:目录操作,这里用于获取用户主目录作为文件对话框的默认路径
#include <QDir>
// QFileInfo:文件信息,这里用于从完整路径中取出文件名(去掉目录部分)
#include <QFileInfo>
// QIcon:图标类,用于切换"有声音 / 静音"按钮的图标
#include <QIcon>
// QUrl:统一资源定位符,本地文件路径需要转换成 QUrl 才能交给播放器
#include <QUrl>
// ================================================================
// 构造函数:完成界面装载、播放器与播放列表初始化、信号槽连接
// ================================================================
QAudioFrePro::QAudioFrePro(QWidget *parent) : QMainWindow(parent) {
// 装载 .ui 文件生成的界面,把界面上的控件挂到 this 上
// 同时会自动查找本类中符合 on_<控件名>_<信号名> 规则的槽函数并完成连接
// (例如 on_pushButton_open_clicked、on_horizontalSlider_volume_valueChanged
// 等)
ui.setupUi(this);
// 创建播放器:this 作为父对象,内存由 this 自动管理
player = new QMediaPlayer(this);
// 创建播放列表:this 作为父对象,内存由 this 自动管理
playlist = new QMediaPlaylist(this);
// 设置播放列表的循环方式:
// Loop = 整个列表循环播放(播完最后一首回到第一首)
// Sequential = 按顺序播放,播完停止
// CurrentItemInLoop = 单曲循环
// Random = 随机播放
playlist->setPlaybackMode(QMediaPlaylist::Loop);
// 把播放列表设置给播放器,之后播放器就会按照列表中的媒体依次播放
player->setPlaylist(playlist);
// --- 下面把播放器的各种状态信号连接到界面的槽函数 ---
// stateChanged(State):播放状态改变(停止/播放/暂停)时触发,
// 槽函数 onstatechg
// 用来切换"播放/暂停/停止"按钮的可用状态
connect(player, SIGNAL(stateChanged(QMediaPlayer::State)), this,
SLOT(onstatechg(QMediaPlayer::State)));
// positionChanged(qint64):播放位置变化时持续触发(毫秒),
// 槽函数 onptchg
// 用来刷新进度条与"当前进度/总时长"文本
connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(onptchg(qint64)));
// durationChanged(qint64):当前媒体的总时长确定后触发(毫秒),
// 槽函数 onDrtchg 用来设置进度条的最大值并保存总时长
connect(player, SIGNAL(durationChanged(qint64)), this,
SLOT(onDrtchg(qint64)));
// currentIndexChanged(int):播放列表当前曲目索引改变时触发,
// 槽函数 onplaylistchg 用来同步列表高亮与歌曲名标签
connect(playlist, SIGNAL(currentIndexChanged(int)), this,
SLOT(onplaylistchg(int)));
// 初始化音量:音量滑块在 .ui 中默认值为 50,
// 而播放器默认音量是 100,因此启动时把播放器音量与界面滑块的值保持一致
player->setVolume(ui.horizontalSlider_volume->value());
}
// ================================================================
// 析构函数
// player、playlist 都以 this 为父对象,Qt 会随窗口一起自动销毁,
// 因此这里无需手动 delete
// ================================================================
QAudioFrePro::~QAudioFrePro() {}
// ================================================================
// 【打开】按钮:弹出文件对话框,把选中的音频文件加入播放列表并播放
// 信号:pushButton_open 的 clicked()
// ================================================================
void QAudioFrePro::on_pushButton_open_clicked() {
// getOpenFileNames 可一次选择多个文件,返回选中的完整路径列表
// 参数依次为:父窗口、对话框标题、默认打开目录(用户主目录)、文件类型过滤器
QStringList fileNames = QFileDialog::getOpenFileNames(
this, tr("选择音频文件"), QDir::homePath(),
tr("音频文件 (*.mp3 *.wav *.flac *.ogg *.aac *.wma);;所有文件 (*.*)"));
// 用户点了"取消"或没有选择任何文件时直接返回,不做任何处理
if (fileNames.isEmpty())
return;
// 遍历用户选中的每个文件:
for (const QString &fileName : fileNames) {
// 1) 把本地路径转换成 QUrl
// 后加入播放列表(注意是增量添加,不会清空已有歌曲)
playlist->addMedia(QUrl::fromLocalFile(fileName));
// 2) 取出文件名(不含目录,例如 "C:\music\a.mp3" ->
// "a.mp3")显示到列表控件,
// 行号顺序与播放列表中的索引一一对应,供双击/切歌时互相定位
ui.listWidget_MusicList->addItem(QFileInfo(fileName).fileName());
}
// 若之前还没有任何歌曲(currentIndex 为 -1),把播放列表定位到第一首
if (playlist->mediaCount() > 0 && playlist->currentIndex() < 0)
playlist->setCurrentIndex(0);
// 开始播放(列表切换曲目会触发 onplaylistchg 同步界面高亮)
player->play();
}
// ================================================================
// 【播放】按钮:播放当前选中的歌曲
// 信号:pushButton_play 的 clicked()
// 说明:首次播放前必须先通过"打开"按钮添加歌曲
// ================================================================
void QAudioFrePro::on_pushButton_play_clicked() {
// 播放列表为空时什么都不做,避免无效操作
if (playlist->mediaCount() <= 0)
return; // 还没有歌曲,请先点击"打开"
// 如果还没有选中任何歌曲(例如打开文件后处于停止状态),定位到第一首
if (playlist->currentIndex() < 0)
playlist->setCurrentIndex(0);
// 开始/继续播放(若处于暂停状态,play() 会从暂停位置继续)
player->play();
}
// ================================================================
// 【暂停】按钮:暂停当前播放
// 信号:pushButton_pause 的 clicked()
// 说明:暂停后再次点击"播放"会从暂停位置继续,而不是从头播放
// ================================================================
void QAudioFrePro::on_pushButton_pause_clicked() { player->pause(); }
// ================================================================
// 【停止】按钮:停止当前播放
// 信号:pushButton_stop 的 clicked()
// 说明:停止后再点"播放",歌曲会从头开始
// ================================================================
void QAudioFrePro::on_pushButton_stop_clicked() { player->stop(); }
// ================================================================
// 【上一曲】按钮:切到播放列表的上一首并播放
// 信号:pushButton_previous 的 clicked()
// ================================================================
void QAudioFrePro::on_pushButton_previous_clicked() {
// 列表为空时不响应
if (playlist->mediaCount() <= 0)
return;
// previous():跳到上一首;若当前是第一首且模式为 Loop,会循环到最后一首
playlist->previous();
// 切歌后立即开始播放
player->play();
}
// ================================================================
// 【下一曲】按钮:切到播放列表的下一首并播放
// 信号:pushButton_next 的 clicked()
// ================================================================
void QAudioFrePro::on_pushButton_next_clicked() {
// 列表为空时不响应
if (playlist->mediaCount() <= 0)
return;
// next():跳到下一首;若当前是最后一首且模式为 Loop,会循环回到第一首
playlist->next();
// 切歌后立即开始播放
player->play();
}
// ================================================================
// 【音量】按钮:在"静音"和"取消静音"之间切换(即打开/关闭声音)
// 信号:pushButton_volume 的 clicked()
// 说明:静音时图标切换为 mute.bmp,恢复声音时图标切回 volumn.bmp
// ================================================================
void QAudioFrePro::on_pushButton_volume_clicked() {
if (player->isMuted()) {
// 当前是静音状态 -> 取消静音
player->setMuted(false);
ui.pushButton_volume->setIcon(QIcon(":/QAudioFrePro/images/volumn.bmp"));
} else {
// 当前有声音 -> 开启静音
player->setMuted(true);
ui.pushButton_volume->setIcon(QIcon(":/QAudioFrePro/images/mute.bmp"));
}
}
// ================================================================
// 【音量滑块】槽函数:用户拖拽滑块时实时调整音量大小
// 信号:horizontalSlider_volume 的 valueChanged(int),value 取值 0~100
// ================================================================
void QAudioFrePro::on_horizontalSlider_volume_valueChanged(int value) {
// 把滑块的数值(0~100)直接设置为播放器的音量
player->setVolume(value);
// 若当前处于静音状态,只要拖动滑块就自动解除静音并恢复图标,
// 避免"拖了滑块却没声音"让用户误以为坏了
if (player->isMuted()) {
player->setMuted(false);
ui.pushButton_volume->setIcon(QIcon(":/QAudioFrePro/images/volumn.bmp"));
}
}
// ================================================================
// 【播放进度滑块】槽函数:拖拽结束后把歌曲跳转到滑块所在位置
// 信号:horizontalSlider_spead 的 sliderReleased()(鼠标松开时触发)
// 说明:不使用 valueChanged 是因为播放中 onptchg 会不断刷新滑块位置,
// 若实时跳转会相互干扰、造成拖拽抖动;松手时一次性跳转体验更好,
// 且与 onptchg 中 isSliderDown() 的防冲突逻辑配合良好。
// ================================================================
void QAudioFrePro::on_horizontalSlider_spead_sliderReleased() {
// 进度条最大值为歌曲总时长(onDrtchg 中设置),value 单位与播放位置一致(毫秒),
// 直接把当前滑块值作为目标播放位置即可
player->setPosition(ui.horizontalSlider_spead->value());
}
// ================================================================
// 【歌曲列表】双击槽函数:双击列表中的某首歌,立即播放它
// 信号:listWidget_MusicList 的 itemDoubleClicked(QListWidgetItem*)
// ================================================================
void QAudioFrePro::on_listWidget_MusicList_itemDoubleClicked(
QListWidgetItem *item) {
// 防御性检查:双击的对象不应为空
if (!item)
return;
// row(item) 返回该项所在的行号。因为"打开"时是把文件逐个同步加入
// 播放列表与列表控件的,行号与播放列表索引一一对应
int row = ui.listWidget_MusicList->row(item);
// 越界检查,防止索引超出播放列表范围
if (row < 0 || row >= playlist->mediaCount())
return;
// 把播放列表的当前曲目切换到该行,会触发 currentIndexChanged 信号,
// 由 onplaylistchg 同步列表高亮与左侧歌曲名标签
playlist->setCurrentIndex(row);
// 开始播放被双击的歌曲
player->play();
}
// ================================================================
// 播放状态变化槽函数:根据播放状态切换下方控制按钮的可用性
// 信号:QMediaPlayer::stateChanged(QMediaPlayer::State)
// State 取值:StoppedState(停止) / PlayingState(播放中) / PausedState(已暂停)
// ================================================================
void QAudioFrePro::onstatechg(QMediaPlayer::State state) {
// 播放中 -> "播放"按钮禁用(当前正在播放无需再点),否则启用
ui.pushButton_play->setEnabled(!(state == QMediaPlayer::PlayingState));
// 播放中 -> "暂停"按钮启用,可点击暂停;非播放状态禁用
ui.pushButton_pause->setEnabled(state == QMediaPlayer::PlayingState);
// 播放中 -> "停止"按钮启用,可点击停止;非播放状态禁用
ui.pushButton_stop->setEnabled(state == QMediaPlayer::PlayingState);
}
// ================================================================
// 播放列表当前曲目变化槽函数:同步界面上的选中高亮与歌曲名标签
// 信号:QMediaPlaylist::currentIndexChanged(int pos),pos 为新的曲目索引
// ================================================================
void QAudioFrePro::onplaylistchg(int pos) {
// 让列表控件高亮播放中的那一行(对应上一曲/下一曲/双击/自动切歌等场景)
ui.listWidget_MusicList->setCurrentRow(pos);
// 取出当前选中的列表项
QListWidgetItem *item = ui.listWidget_MusicList->currentItem();
// 若存在该项,则把歌曲名显示到界面的"歌曲名称"标签上
if (item)
ui.label_mucName->setText(item->text());
}
// ================================================================
// 歌曲总时长变化槽函数:设置进度条最大值并保存总时长文本
// 信号:QMediaPlayer::durationChanged(qint64 drt),drt 为毫秒
// ================================================================
void QAudioFrePro::onDrtchg(qint64 drt) {
// 进度条最大值设为总时长,这样进度条 0 ~ 最大值 恰好对应 0 ~ 总时长
ui.horizontalSlider_spead->setMaximum(drt);
// 毫秒 -> 秒
int sec = drt / 1000;
// 秒 -> 分钟(整除)
int min = sec / 60;
// 去掉整分钟后的剩余秒数
sec = sec % 60;
// 格式化为 "分:秒"(不足两位补 0,例如 03:05),保存为歌曲总时长
drtTime = QString::asprintf("%02d:%02d", min, sec);
// 显示格式:"当前进度 / 总时长",当前进度部分由 onptchg 维护
ui.label_time->setText(pstTime + " / " + drtTime);
}
// ================================================================
// 播放位置变化槽函数:刷新进度条位置与"当前进度/总时长"文本
// 信号:QMediaPlayer::positionChanged(qint64 pos),pos 为毫秒
// ================================================================
void QAudioFrePro::onptchg(qint64 pos) {
// 若用户正在按住进度条拖拽(isSliderDown 为 true),
// 则跳过本次刷新,避免程序与用户"抢"滑块位置,保证拖拽顺畅;
// 等用户松手后由 on_horizontalSlider_spead_sliderReleased 完成跳转
if (ui.horizontalSlider_spead->isSliderDown()) {
return;
}
// 把进度条滑块移动到当前播放位置(setSliderPosition 不会触发 valueChanged,
// 因此不会反向干扰播放)
ui.horizontalSlider_spead->setSliderPosition(pos);
// 与 onDrtchg 相同的换算:毫秒 -> 分:秒 文本
int sec = pos / 1000; // 秒
int min = sec / 60; // 分
sec = sec % 60; // 余数为秒
pstTime = QString::asprintf("%02d:%02d", min, sec); // 保存当前播放进度
// 实时刷新时间标签:当前进度 / 总时长
ui.label_time->setText(pstTime + " / " + drtTime);
}
效果

4.3 界面版补充要点
若使用 Qt Widgets 界面,建议:
- 用
QSlider作为进度条,绑定positionChanged更新滑块、sliderMoved触发setPosition。 - 用
QLabel显示当前曲目名,绑定currentIndexChanged。 - 用
QPushButton控制播放/暂停/上一首/下一首。 - 用
QListWidget显示歌单,双击条目调用setCurrentIndex(row)。
6. 常见坑与 FAQ
6.1 没有声音 / 提示没有音频输出(Qt 6 专属)
Qt 6 中必须手动创建 QAudioOutput:
cpp
QAudioOutput *audioOutput = new QAudioOutput(this);
player->setAudioOutput(audioOutput);
audioOutput->setVolume(0.5f);
6.2 播放不了 MP3 等格式
确认两方面:
- 项目文件已加
QT += multimedia。 - 系统/后端解码器支持该格式。Qt 依赖系统多媒体框架(Windows 用 WMF/DirectShow,Linux 用 GStreamer),确保系统能播放该格式。
6.3 进度条不居中 / 位置异常
duration()在媒体加载完成后才有有效值(LoadedMedia之后)。请在durationChanged或mediaStatusChanged == LoadedMedia后再设置进度条最大值。- 定位前先判断
isSeekable()。
6.4 previous() 行为不符合预期
previous() 在播放超过约 1.5 秒后,大多实现是"回到当前曲目开头"而非"上一首"。要实现真正"上一首",可自行记录历史或连续调用两次(视后端而定)。
6.5 播放列表如何自动连续播放
绑定播放器后,一首播完会自动根据 PlaybackMode 播放下一首,无需手动 connect。若需在最后一首播完停止,用 Sequential 模式即可。
6.6 网络收音机 / 流媒体播放
cpp
player->setMedia(QMediaContent(QUrl("http://example.com/stream"))); // Qt 5
player->setSource(QUrl("http://example.com/stream")); // Qt 6
player->play();
缓冲状态可通过 mediaStatusChanged 的 BufferingMedia / BufferedMedia 判断。
快速参考表
| 需求 | 关键调用 |
|---|---|
| 播放文件 | player->setMedia(...) / setSource(...) + play() |
| 暂停/继续 | player->pause() / player->play() |
| 停止 | player->stop() |
| 调音量 | player->setVolume(...) |
| 静音 | player->setMuted(true) |
| 定位 | player->setPosition(ms) |
| 获取进度 | player->position() |
| 获取时长 | player->duration() |
| 绑定歌单 | player->setPlaylist(playlist) |
| 添加歌曲 | playlist->addMedia(...) |
| 下一首 | playlist->next() |
| 上一首 | playlist->previous() |
| 跳到第 N 首 | playlist->setCurrentIndex(N) |
| 列表循环 | playlist->setPlaybackMode(QMediaPlaylist::Loop) |
| 随机播放 | playlist->setPlaybackMode(QMediaPlaylist::Random) |
| 单曲循环 | playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop) |
完结