c++在线音乐播放器项目开发记录(2)

前言

因为放寒假了,时间比较短,想找实习也不好找,干脆在家加强一下技术栈,首先从c++学起,最适合练手的就是qt的项目了,我是根据B站视频【5个C/C++硬核简历项目实战,可直接写入简历,包含:Qt项目、音视频流媒体开发、后端开发、DPDK网络编程、KV存储、Linux内核。总有一个实战项目适合你!】来进行学习的,这篇文章主要是记录一下在跟视频做的过程中,自己的学习体会和问题的解决思路。

项目已上传至Github:https://github.com/MengFanjun020906/OnlineMusic

1.主窗口添加功能

1.1 进度条控件美化

 // 播放进度条控件美化
    ui->horizontalSlider_PlayProgress->setStyleSheet("QSlider::groove:horizontal {"
                                                     "    border: 1px solid #bbb;"
                                                     "    background: white;"
                                                     "    height: 10px;"
                                                     "    border-radius: 5px;"
                                                     "}"
                                                     "QSlider::sub-page:horizontal {"
                                                     "    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #66e, stop: 1 #bbf);"
                                                     "    border: 1px solid #777;"
                                                     "    height: 10px;"
                                                     "    border-radius: 5px;"
                                                     "}"
                                                     "QSlider::add-page:horizontal {"
                                                     "    background: #fff;"
                                                     "    border: 1px solid #777;"
                                                     "    height: 10px;"
                                                     "    border-radius: 5px;"
                                                     "}"
                                                     "QSlider::handle:horizontal {"
                                                     "    background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eee, stop:1 #ccc);"
                                                     "    border: 1px solid #777;"
                                                     "    width: 18px;"
                                                     "    margin-top: -4px;"
                                                     "    margin-bottom: -4px;"
                                                     "    border-radius: 9px;"
                                                     "}");


    ui->horizontalSlider_Volume->setStyleSheet("QSlider::groove:horizontal {"
                                                     "    border: 1px solid #bbb;"
                                                     "    background: white;"
                                                     "    height: 10px;"
                                                     "    border-radius: 5px;"
                                                     "}"
                                                     "QSlider::sub-page:horizontal {"
                                                     "    background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #66e, stop: 1 #bbf);"
                                                     "    border: 1px solid #777;"
                                                     "    height: 10px;"
                                                     "    border-radius: 5px;"
                                                     "}"
                                                     "QSlider::add-page:horizontal {"
                                                     "    background: #fff;"
                                                     "    border: 1px solid #777;"
                                                     "    height: 10px;"
                                                     "    border-radius: 5px;"
                                                     "}"
                                                     "QSlider::handle:horizontal {"
                                                     "    background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 #eee, stop:1 #ccc);"
                                                     "    border: 1px solid #777;"
                                                     "    width: 18px;"
                                                     "    margin-top: -4px;"
                                                     "    margin-bottom: -4px;"
                                                     "    border-radius: 9px;"
                                                     "}");

实现的效果如下,虽然也不是特别好看,但是效果比原来的好看得多。
在这里插入图片描述

1.2 初始化多媒体实例

因为qt6的MediaPlayList被移除了,所以需要我们自己写playlist的相关函数和头文件,但如果是qt5的话,这个类就可以正常使用

    //将光标焦点定位到搜索歌曲名称的控件
    ui->lineEdit_InputSong->setFocus();

    //初始化
    NetworkAccessManager = new QNetworkAccessManager(this);

    iPos=0;

    //初始文本对象
    docTextObject = ui->plainTextEdit_SongList->document();

    //将控件设置为只读
    ui->plainTextEdit_SongList->setReadOnly(true);

    //初始化多媒体实例
    p_PlayerObject=new QMediaPlayer(this);
    //p_PlayerList = new
    Playlist *p_PlayList = new Playlist(this);

    //设置播放模式
    p_PlayList->setPlaybackMode(Playlist::Loop);

    //信号与槽处理如下
    connect(p_PlayerObject,SIGNAL(positionChanged(qint64)),this,SLOT(HandleLCDNumberTimeChangeFunc(qint64)));
    connect(p_PlayerObject,SIGNAL(positionChanged(qint64)),this,SLOT(HandlePositionChangeFunc(qint64)));
    connect(p_PlayerObject,SIGNAL(positionChanged(qint64)),this,SLOT(HandleProgressTimeChangeFunc(qint64)));
    connect(NetworkAccessManager,SIGNAL(finished(QNetworkReply*)),this,SLOT(HandleDataBackFunc(QNetworkReply*)));

2.搜索歌曲显示歌手功能

这个函数是 OnlineMusicWidget 类的一个槽函数,它会在 pushButton_SearchSong 按钮被点击时触发。其主要功能是根据用户在 lineEdit_InputSong 输入框中输入的歌曲名称,向网易云音乐的搜索 API 发送一个 GET 请求,以获取相关歌曲的搜索结果。

void OnlineMusicWidget::HandleDataBackFunc(QNetworkReply *pReply)
{
    //读取网络回款数据
    QByteArySearchInfo = pReply->readAll();

    QJsonParseError JSonPError;//定义错误信息对象

    //将json文本转换为json文件对象
    QJsonDocument JSonDoc_RecvData=QJsonDocument::fromJson(QByteArySearchInfo,&JSonPError);
    if(JSonPError.error!=QJsonParseError::NoError)//判断是否符合规则
    {
        QMessageBox::critical(this,"Prompt","提示:获取歌曲json出错,请重新检查",QMessageBox::Yes);
        return;
    }
    //QJsonObject使用函数object();
    QJsonObject TotalJsonObject = JSonDoc_RecvData.object();

    //列出json里面的所有key
    QStringList strKeys=TotalJsonObject.keys();

    if(strKeys.contains("result"))//与数据信息
    {
        //将带有result的数据内容提取之后转换为对象
        QJsonObject resultobject=TotalJsonObject["result"].toObject();

        //存储所有keys
        QStringList strResultKeys=resultobject.keys();

        if(strResultKeys.contains("songs"))
        {
            QJsonArray array=resultobject["songs"].toArray();

            //通过for循环查找歌曲当中的字段信息
            for(auto isong:array)
            {
                QJsonObject jsonobject1 = isong.toObject();
                //获取歌曲ID 歌名 歌手
                I_MusicID = jsonobject1["id"].toInt();
                StrMusicName = jsonobject1["name"].toString();


                QStringList strkeys = jsonobject1.keys();

                if(strkeys.contains("artists"))
                {
                    QJsonArray artitstsjsonarray= jsonobject1["artists"].toArray();
                    for(auto js:artitstsjsonarray)
                    {
                        QJsonObject jsonobject2=js.toObject();
                        StrSingerName = jsonobject2["name"].toString();
                    }
                }
            }
        }

    }
    // 生成歌曲 URL
    QString url = QString("https://music.163.com/song/media/outer/url?id=%0").arg(I_MusicID);

    // 创建一个 QVariantMap 并将歌曲 URL 存储在 "path" 键下
    QVariantMap song;
    song["path"] = url;
    // 调用 appendSong 函数将歌曲添加到播放列表
    p_PlayList->appendSong(song);

    ui->plainTextEdit_SongList->appendPlainText(StrMusicName+"-"+StrSingerName);
}
//搜索歌曲名称实现
void OnlineMusicWidget::on_pushButton_SearchSong_clicked()
{
    QString str1,str2;
    str1=ui->lineEdit_InputSong->text();


    str2="http://music.163.com/api/search/get/web?csrf_token=hlpretag=&hlposttag=&s={"+str1+"}&type=1&offset=0&total=true&limit=1";

    //定义一个请求对象
    QNetworkRequest networkRequest;
    networkRequest.setUrl(str2);

    //将请求格式设置给对应请求对象
    networkRequest.setUrl(str2);
    //使用QNetworkAccessManager类对应的API发送GET请求并获取响应数据



    NetworkAccessManager->get(networkRequest);

}

在这里插入图片描述

3.播放功能

3.1 播放按钮播放

从回传的id去获取歌曲的url,但是需要注意的是,VIP歌曲不能播放,网易云的网页版和APP版还不一样,网页版连试听都没有,我再搜岁歌曲的时候,发现怎么着都播放不出来,选几首比较冷门的歌,才发现原来问题是没有开vip。

//播放歌曲
void OnlineMusicWidget::on_pushButton_PlaySong_clicked()
{




    qDebug() << "播放列表内容:" << playList;
    qDebug() << "当前播放索引:" << currentIndex;
    qDebug() << "播放器状态:" << p_PlayerObject->playbackState();
    qDebug() << "[Debug] 当前播放器状态:" << p_PlayerObject->playbackState();

    // 1. 处理空播放列表
    if (playList.isEmpty()) {
        QMessageBox::warning(this, "错误", "播放列表为空");
        return;
    }

    // 2. 自动定位到第一首
    if (currentIndex == -1) {
        currentIndex = 0;
    }

    // 3. 核心逻辑
    switch (p_PlayerObject->playbackState()) {
    case QMediaPlayer::StoppedState:  // 停止状态
    case QMediaPlayer::PausedState:   // 暂停状态
        // 只有源文件变化时才重新设置
        if (p_PlayerObject->source() != playList[currentIndex]) {
            p_PlayerObject->setSource(playList[currentIndex]);
        }
        p_PlayerObject->play();
        //ui->pushButton_PlaySong->setText("暂停");
        break;

    case QMediaPlayer::PlayingState:  // 正在播放
        p_PlayerObject->pause();
        //ui->pushButton_PlaySong->setText("播放");
        break;

    default:  // 无媒体或错误状态
        p_PlayerObject->setSource(playList[currentIndex]);
        p_PlayerObject->play();
        //ui->pushButton_PlaySong->setText("暂停");
        break;
    }
}

3.2 暂停与停止功能

这里直接调用PlayerObject的函数即可

//暂停播放
void OnlineMusicWidget::on_pushButton_PauseSong_clicked()
{
    // 只有正在播放时才能暂停
    if (p_PlayerObject->playbackState() == QMediaPlayer::PlayingState) {
        p_PlayerObject->pause();
        //ui->pushButton_PlaySong->setText("播放"); // 同步更新播放按钮状态
        qDebug() << "音乐已暂停";
    }
}

//停止播放
void OnlineMusicWidget::on_pushButton_StopPlaySong_clicked()
{
    if (p_PlayerObject->playbackState() != QMediaPlayer::StoppedState) {
        p_PlayerObject->stop();
        //ui->pushButton_PlaySong->setText("播放");  // 强制更新播放按钮状态
        qDebug() << "音乐已停止";
    }
}

3.3 上一曲与下一曲的切换

//播放上一曲
void OnlineMusicWidget::on_pushButton_PreviousSong_clicked()
{

    if (playList.isEmpty()) {
        QMessageBox::warning(this, "提示", "播放列表为空");
        return;
    }


    // 计算新索引(支持循环)
    currentIndex = (currentIndex - 1 + playList.size()) % playList.size();

    // 设置新播放源
    p_PlayerObject->setSource(playList[currentIndex]);

    // 自动开始播放
    p_PlayerObject->play();
    qDebug() << "上一曲";


}
//播放下一曲
void OnlineMusicWidget::on_pushButton_NextSong_2_clicked()
{
    if (playList.isEmpty()) {
        QMessageBox::warning(this, "提示", "播放列表为空");
        return;
    }

    // 计算新索引(支持循环)
    currentIndex = (currentIndex + 1) % playList.size();

    // 设置新播放源
    p_PlayerObject->setSource(playList[currentIndex]);

    // 自动开始播放
    p_PlayerObject->play();
    qDebug() << "下一曲";

}

4.音量控制

静音实现

void OnlineMusicWidget::on_pushButton_SoundYesNo_clicked()
{
    QAudioOutput* audioOutput = p_PlayerObject->audioOutput();

    if (isMuted) {
        // 取消静音,恢复之前音量
        audioOutput->setMuted(false);
        audioOutput->setVolume(previousVolume);
        ui->horizontalSlider_Volume->setValue(previousVolume * 100);
        ui->pushButton_SoundYesNo->setIcon(QIcon(":/new/prefix1/Images/MSound.png"));
        qDebug() << "取消静音,恢复音量到:" << previousVolume;
    } else {
        // 记录当前音量并静音
        previousVolume = audioOutput->volume();
        audioOutput->setMuted(true);
        ui->pushButton_SoundYesNo->setIcon(QIcon(":/new/prefix1/Images/MNoSound.png"));
        qDebug() << "静音,原音量:" << previousVolume;
    }

    isMuted = !isMuted;  // 切换状态

}

拖动滑块改变歌曲音量

//音量控制
void OnlineMusicWidget::on_horizontalSlider_Volume_valueChanged(int value)
{
    QAudioOutput* audioOutput = p_PlayerObject->audioOutput();

    // 将滑块值(0-100)转换为浮点音量(0.0-1.0)
    qreal volume = qBound(0.0, value / 100.0, 1.0);
    audioOutput->setVolume(volume);

    // 同步静音状态
    if (volume > 0 && audioOutput->isMuted()) {
        audioOutput->setMuted(false);
        ui->pushButton_SoundYesNo->setIcon(QIcon(":/new/prefix1/Images/MSound.png"));
        isMuted = false;
    }


}

5.歌曲时间显示

在进度条右侧的LCD数字会显示歌曲的时长

//处理LCD控件时间变化
void OnlineMusicWidget::HandleLCDNumberTimeChangeFunc(qint64 duration)
{
    int int_Second=duration/1000;
    int int_Minute=int_Second/60;
    int_Second=int_Second%60;
    QString strSongTime=QString::asprintf("%d:%d",int_Minute,int_Second);
    ui->lcdNumber_PlayTime->display(strSongTime);
}

歌曲的进度条会随着播放而变化

// 处理进度条控件变化
void OnlineMusicWidget::HandleProgressTimeChangeFunc(qint64 duration)
{
    //设置进度条最大值
    ui->horizontalSlider_PlayProgress->setMaximum(duration);
}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sol-itude

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值