Qt_QMediaPlayer类与QMediaPlaylist类

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 中,QMediaPlayerQMediaPlaylist 属于 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 等格式

确认两方面:

  1. 项目文件已加 QT += multimedia
  2. 系统/后端解码器支持该格式。Qt 依赖系统多媒体框架(Windows 用 WMF/DirectShow,Linux 用 GStreamer),确保系统能播放该格式。

6.3 进度条不居中 / 位置异常

  • duration() 在媒体加载完成后才有有效值(LoadedMedia 之后)。请在 durationChangedmediaStatusChanged == 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();

缓冲状态可通过 mediaStatusChangedBufferingMedia / 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)

完结

相关推荐
mengzhi啊1 小时前
QT程序界面自适应1080/2K/4K屏幕。qputenv或者setAttribute
qt
统计学小王子1 小时前
数学建模国赛倒计时6天——《软件工具(R语言精讲)》
开发语言·数学建模·r语言
C++ 老炮儿的技术栈1 小时前
Qt5 使用 QPainter 绘制阿基米德螺线
开发语言·c++·windows·qt·代码化
EasyGBS1 小时前
从接入到稳定播放:无插件直播H5视频流媒体播放器EasyPlayer.js如何撑起Web端流媒体
开发语言·前端·javascript
FfHUCisI1 小时前
GMP 调度器:Go 并发的心脏是如何跳动的
开发语言·golang·php
Java小白笔记1 小时前
Java 实现阿里云 OSS 文件上传链路:普通上传、秒传、分片与断点续传
java·开发语言·数据库·spring·阿里云
传奇开心果编程1 小时前
【Rust入门知识点学与练】第9课:Vec 动态数组
开发语言·学习·rust
卢锡荣1 小时前
单芯掌控多口互联|乐得瑞 LDR6020 PD3.1 多通道 Type‑C 控制 SOC 芯片
c语言·开发语言
2333!!!!!1 小时前
rocket新手一些常见问题
java·开发语言