QT 离线音乐播放器

        今天刚做完一个简单的智能家居项目,里面包含了一个比较简单的音乐播放器,为了加深一下对这个东西印象,所以把操作流程以及一些用到的类和方法记录一下。

目录

1.UI界面制作

2.加入播放器类

3.播放器初始化

4.功能控件

        4.1 播放、暂停、切换歌曲

         4.2 添加、删除、清空

        4.3 音量控制

        4.4 进度条

5. 总结


1.UI界面制作

        作为一个音乐播放器,最基础的肯定就是播放、暂停、上一首以及下一首,为了使这个界面好看一点,还加入了音量控制、进度条、歌曲列表等内容,至于这种配色和效果好不好看,我也不知道,个人审美一如既往的不达标。

         QT设计界面有两种方式,一种是直接通过纯代码的方式实现,将各种控件以及布局通过代码的方式编排成一个完整的UI界面,但是这种方式较为麻烦也比较复杂,代码量也比较大,还有一种就是通过UI文件拖拽QT控件,来对整个布局进行排版的效果,我这里为了省事采用的就是这种方式,至于实际效果怎么样那就要看个人审美了。

        整个UI界面内部使用到的基础控件有以下几种:

控件名称控件类控件功能
ToolButton QToolButton用来控制暂停、播放、切换歌曲的功能
PushButtonQPushButton用来控制添加、删除、清空歌曲列表的功能
horizontalSliderQSlider

用来控制播放进度、音量等功能

listWidgetQListWidget歌单列表,内部存入添加的歌曲
groupBoxQgroupBox内部放入播放列表
labelQlabel标签,可以用来显示提示信息以及图片

        

2.加入播放器类

        UI界面设计完成之后就是加入播放器类。QT中使用播放器类需要加入对应的链接模块,通过查询QT的帮助手册可以查到,然后在项目的pro文件中加上即可。

         加入链接模块后,需要添加我们需要使用到的一些相关的播放器类头文件

#include <QMediaPlayer>        //播放器类
#include <QMediaPlaylist>      //播放器列表类

3.播放器初始化

        我们的播放器和播放器列表从创建、使用、以及最后程序结束的释放都是同一个,这样有礼物我们对于整个播放器的管理,所以我们要保证初始化时创建的播放器在我们的程序运行阶段一直存在而不会应该哪个程序结束而被释放掉,所以我们要在界面类的成员中添加播放器和播放器列表。

class Widget : public QWidget
{
    Q_OBJECT

public:
    explicit Widget(QWidget *parent = 0);
    ~Widget();

    void Music_Init();        //音乐播放器初始化函数

public slots:

private:
    Ui::Widget *ui;

    QMovie * Music_GIF;            //GIF动态图片(就是封面上的周杰伦的那个图片)
    QMediaPlayer *my_Player;       //播放器类成员
    QMediaPlaylist *my_PlayerList; //播放器列表类成员

};

         这里的Music_GIF成员是用来设置动态图片的,因为我们在后面的设计中,需要按下暂停键可以暂停GIF所以加入了这个成员。

void Widget::Music_Init()
{
    Music_GIF = new QMovie(":/图标资源/周杰伦GIF.gif");
    my_Player = new QMediaPlayer;
    my_PlayerList =new QMediaPlaylist;
   
    my_Player->setPlaylist(my_PlayerList);                 //设置播放列表
    my_PlayerList->setPlaybackMode(QMediaPlaylist::Loop);  //设置播放模式     


//如果需要初始化时播放列表中就存在歌曲可以加入下面的代码
//如果没有需要可以暂时不加
    QList<QUrl> Url;    //创建一个链接列表
    QUrl url = QUrl::fromLocalFile("E:\\QT\\QT_Widget\\SmartHome\\音频资源\\爱在西元前-周杰伦.mp3");    //可以自动读取到指定目录下的歌曲,加入到链接列表中

    for(auto url_list : Url)    //通过循环的方式,把链接列表添加到播放列表中
    {
        ui->listWidget->addItem(url_list.fileName());        //添加到UI界面中的listWidget中
        my_PlayerList->addMedia(QMediaContent(url_list));    //添加到播放器列表中
    }
}

4.功能控件

        对于功能的设计无非就是通过代码来实现你所设计的这些控件的基本功能。

        4.1 播放、暂停、切换歌曲

         这一功能我采用的是三个ToolButoon来控制的,pushButoon按钮和toolButton按钮的使用方式是一样的,但是toolButton可以设置Icon,即可以让按钮显示图标,而不影响其内部的Text文本,pushButton按钮没有Icon设置,只能是文字形式,这个地方我的表达可能不是很清楚,但是大家动手实验一下应该就可以明白了。

        设置好按钮后就可以开始搭建功能,首先是连接好按钮的信号与槽函数。主要有两种方式,我使用的是第二种,大家可以自行选择。

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);

    Music_Init();
/******************************* 方式一 ***********************************/
//设置按钮来控制播放器的播放、暂停、切换等功能可以直接使用播放器类中自带的槽函数
    connect(ui->toolButton_play,SIGNAL(clicked(bool)),my_Player,SLOT(play()));
    connect(ui->toolButton_next,SIGNAL(clicked(bool)),my_Player,SLOT(play()));
    connect(ui->toolButton_prev,SIGNAL(clicked(bool)),my_Player,SLOT(play()));

//在本设计中暂停按键没有,是通过改变播放按键的功能来实现的暂停,如果大家需要一个按键单独控制暂停可以使用下方函数
    connect(ui->toolButton_pause,SIGNAL(clicked(bool)),my_Player,SLOT(play()));
    
/******************************* 方式二 ***********************************/
//因为我这里按下按钮之后需要控制按钮的图标改变,所以这里没有直接链接到播放器的槽函数,而是自己写的一个槽函数
    //播放按钮
    connect(ui->toolButton_play,SIGNAL(clicked(bool)),this,SLOT(slot_toolButton_Music_Contrl()));
    //下一首按钮
    connect(ui->toolButton_next,SIGNAL(clicked(bool)),this,SLOT(slot_toolButton_Music_Contrl()));
    //上一首按钮    
    connect(ui->toolButton_prev,SIGNAL(clicked(bool)),this,SLOT(slot_toolButton_Music_Contrl()));

//两种方式选择一种即可,这里我采用的是第二种方式。
}

使用的第二种方式的话槽函数需要自己写出来,下面就是我的整个槽函数的设置。

void Widget::slot_toolButton_Music_Contrl()
{
    QToolButton * button = (QToolButton *)sender();    //获取当前按键
    if(my_PlayerList->isEmpty() == false)       //判断当前播放列表是否为空
    {
        ui->listWidget->setCurrentRow(0);       //设置自动选择第一首歌
        if(button->text() == "播放")    //判断当前按键是否为播放
        {
            int index = my_PlayerList->currentIndex();    //获取当前歌曲的下标
            QListWidgetItem *Song_Item =ui->listWidget->item(index);    //获取当前播放歌曲的歌名
            QString song_name = Song_Item.text();    
            //将当前歌名存入song_name中,因为我没有设置这个控件,所以这里并不使用这个变量,若大家需要可以参考,自行设置

            Music_GIF->start();    //播放封面GIF
            my_Player->play();     //播放歌曲
            ui->toolButton_play->setIcon(*music_contrl_pause);    //修改播放按键设置,使其下一次的功能改为暂停
            ui->toolButton_play->setText("暂停");    //修改播放按键的文本,便于下一次分辨
        }else if(button->text() == "暂停")
        {
            Music_GIF->stop();
            my_Player->pause();
            ui->toolButton_play->setIcon(*music_contrl_play);
            ui->toolButton_play->setText("播放");

        }else if(button->text() == "上一首")
        {
            Music_GIF->start();
            my_Player->play();
            ui->toolButton_play->setIcon(*music_contrl_pause);
            ui->toolButton_play->setText("暂停");
            my_PlayerList->previous();    //切换歌曲效果是播放列表类的功能,所以操作播放列表成员
        }else if(button->text() == "下一首")
        {
            Music_GIF->start();
            my_Player->play();
            ui->toolButton_play->setIcon(*music_contrl_pause);
            ui->toolButton_play->setText("暂停");
            my_PlayerList->next();    
        }
        ui->label_GIF->setMovie(Music_GIF);    //更新封面GIF的状态
    }else
    {
        //此功能需要加入头文件 #include <QMessageBox>
        QMessageBox::warning(this,"播放失败","未找到音频文件");    //提示会话弹窗
        
    }
}

         4.2 添加、删除、清空

         添加、删除、清空这三个按键的话,就没有前面的播放那些按键那么复杂,不需要考虑太多的美观问题,只需要实现功能即可。首先也是需要先连接到信号槽

        在这里我写一个另外的方式来实现槽函数的连接,那就是UI界面中的转到槽功能

         通过转到槽的方式,QT会自动声明和定义空槽函数,并将对应的按键连接到此槽函数,我们只需要在空的槽函数中填入代码就可以实现基本功能。

void Widget::on_toolButton_add_music_clicked()    //新增按键槽函数
{
    //这个功能需要加入两个头文件 #include <QFile>
    //                         #include <QFileDialog>
    QList<QUrl> play_list = QFileDialog::getOpenFileUrls(this,"添加音乐");    //添加音乐
    //这串代码会打开一个文件会话窗口,我们可以选择其中的音频文件,QT会以url链接的形式填入列表中
  
    for(auto musiclist : play_list)    //通过循环插入
    {
        my_PlayerList->addMedia(QMediaContent(musiclist));      //插入播放列表  
        ui->listWidget->addItem(musiclist.fileName());          //插入listWidget列表
    }
}

void Widget::on_toolButton_delete_music_clicked()    //删除按键槽函数
{
    int row = ui->listWidget->currentRow(); //获取当前指针所在行
    if(row != -1)
    {
        ui->listWidget->takeItem(row);      //从列表界面中删除
        my_PlayerList->removeMedia(row);    //从播放器列表中删除
        Music_GIF->stop();                  //停止播放GIF
        ui->label_GIF->setMovie(Music_GIF); //刷新GIF状态
    }
}

void Widget::on_toolButton_clear_music_clicked()    //清空按键槽函数
{
    ui->listWidget->clear();    //清空listWidget控件
    my_Player->stop();          //停止播放歌曲
    Music_GIF->stop();          //停止播放GIF
    ui->label_GIF->setMovie(Music_GIF);    //刷新GIF状态
    my_PlayerList->clear();     //清空播放列表
    ui->toolButton_play->setIcon(*music_contrl_play);    //修改播放按键图标
    ui->toolButton_play->setText("播放");                //修改播放按键名称
}

以上就是添加、删除、清空的实现代码。

        4.3 音量控制

        音量控制使用的是水平滑块来实现

//在播放器类中,自带有设置播放音量的槽函数,我们只需要将滑块控件链接到槽即可。
//当水平滑块的值发生改变时,发送信号
connect(ui->horizontalSlider_volume,SIGNAL(valueChanged(int)),my_Player,SLOT(setVolume(int)));

        为了更加人性化以及美观,在音量控制这一块,我还加入了图标的变化,通过不同的音量控制不同的图标。

         首先也是连接到槽函数,这里的话一个信号是可以连到多个槽函数,一个槽函数也可以有多个信号触发,所以这边我们再通过音量的水平滑块来控制图标变化。

//当水平滑块值发生改变时触发
    connect(ui->horizontalSlider_volume,SIGNAL(valueChanged(int)),this,SLOT(solt_horizontalSlider_volume_Icon(int)));

         槽函数如下:

void Widget::solt_horizontalSlider_volume_Icon(int value)
{
    QPixmap *Mute = new QPixmap(":/图标资源/静音.png");        //添加图标资源
    QPixmap *small = new QPixmap(":/图标资源/音量小.png");
    QPixmap *middle = new QPixmap(":/图标资源/音量中.png");
    QPixmap *big = new QPixmap(":/图标资源/音量大.png");
    if(value == 0)    //值为0
    {
        ui->label_volume->setPixmap(*Mute);    //图标为静音
    }else if(value <= 33)
    {
        ui->label_volume->setPixmap(*small );    //图标为小音量
    }else if(value <= 66)
    {
        ui->label_volume->setPixmap(*middle);    //图标为中音量
    }else if(value <= 100)
    {
        ui->label_volume->setPixmap(*big );    //图标为大音量
    }
}

         在UI设计时,初始的滑块样式是这个样子的

 改变其样式表可以改成我上面的那种样子,样式表代码如下:

QSlider::groove:horizontal {

border: none;

height: 6px;

border-radius: 3px;

background: lightgray;

}

QSlider::handle:horizontal {

border: none;

margin: -5px 0px; /* 上下边距和左右边距*/

width: 16px;

height: 16px;

border-radius: 8px;

background: rgb(255, 120, 0);

border-image: url(:/imagesayPbHandle16_White.png);

}

/*划过部分*/

QSlider::sub-page:horizontal {

background: rgb(255, 170, 0);

height: 4px;

border-radius: 3px;

}

/*未划过部分*/

QSlider::add-page:horizontal {

background: lightgray;

height: 4px;

border-radius: 3px;

}

通过这些设置基本上音量控制也弄的差不多了。

        4.4 进度条

        进度条的UI设置主要有两个控件,一个是显示的当前播放进度、总时长的Qlabel控件、一个是显示当前进度的水平滑块控件。

         播放进度的设置,需要通过两个QMediaPlayer类中的函数来实现,通过查询QT的帮助手册,找到了这两个函数的基本信息。

 这个函数可以获取到当前播放媒体的总时长,它的返回值是一个qint64的毫秒值。

 这个函数的作用是返回当前播放媒体的当前播放进度,返回值也是一个qint64的毫秒值。

        这两个函数都有一个自带的信号,分别是:

         durationChanged信号在我们切换到一个新媒体文件的时候会发送一个信号,并发送新切换到的媒体的总时长,也是一个qint64的毫秒值,我们可以通过槽函数接收这个值。

         positionChanged信号是在我们的当前播放进度发生改变的时候会触发的一个信号,它会发送一个当前媒体的当前播放进度,是一个qint64的毫秒值,通过槽函数接收这个值。

有了以上的函数介绍,我们基本上可以实现一个简单的进度条功能。

//当前播放进度改变的信号  
connect(my_Player,SIGNAL(positionChanged(qint64)),this,SLOT(slot_positionchange(qint64)));
//播放媒体切换改变的信号  
connect(my_Player,SIGNAL(durationChanged(qint64)),this,SLOT(slot_durationChanged(qint64)));
//拖动进度条改变播放进度    
connect(ui->horizontalSlider_Playbac_progress,SIGNAL(valueChanged(int)),this,SLOT(slot_valueChanged_progress(int)));

        通过槽函数来实现其基本功能,槽函数如下:

//当前进度改变槽函数
void Widget::slot_positionchange(qint64 value)
{
    //获取到歌曲总时长
    ui->horizontalSlider_Playbac_progress->setMaximum(my_Player->duration()/1000);// 设置进度条最大长度为总时长
    ui->horizontalSlider_Playbac_progress->setValue(value/1000);//设置进度条的当前位置
    
    //QTimer类需要引入头文件#include <QTimer>
    QTime time(0,(value/60000),(value/1000)%60);       //将毫秒数转换成时间格式
    ui->label_now->setText(time.toString("mm:ss"));    //将时间按照指定格式放入Qlabel标签中
}

//当前媒体总时长改变槽函数
void Widget::slot_durationChanged(qint64 value)
{
    QTime time(0,(value/60000)%60,(value/1000)%60);    //将收到的总时长转换成时间格式
    ui->label_max->setText(time.toString("mm:ss"));    //将时间放入到指定标签中
}

//进度条滑块数值改变槽函数
void Widget::slot_valueChanged_progress(int value)   
{
    my_Player->setPosition(value*1000);    //设置播放器的当前进度
}

到这里基本上播放器的进度条设置就实现完成了。

5. 总结

        到这里基本是一个简单的音乐播放器就基本实现了,虽然里面有很多功能写的不是很详细,也有一部分操作我没有做,但是基本能实现播放、暂停、切换等基本功能。

        如果后期需要对播放器的功能进行添加可以自行添加,比方说,QT有自带的视频播放功能,可以将中间的GIF图片换成播放歌曲的MV,还可以添加一个comboBox控件来选择当前播放器的播放模式,QT有内置的宏可以直接设置,我这里是直接选择的循环播放。

        还有就是好像可以实现从网络获取歌曲的方法,这种的话就可以不用提前下载好歌曲了,大家可以自己去找一下,不要问我为什么没做这种,问就是我是菜鸡,我不会。

        好了,差不多到这里也要结束了,作为一个QT的初学者,里面有很多设置方法在各位大佬看来可能很笨,但是目前就只有这种水平了,而且大家如果对各种基础控件的样式不满意,可以去自己找一下各种样式表,自己设置一下,我这里就没有做太多这种操作了。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值