? ? ? ? 今天剛做完一個(gè)簡(jiǎn)單的智能家居項(xiàng)目,里面包含了一個(gè)比較簡(jiǎn)單的音樂播放器,為了加深一下對(duì)這個(gè)東西印象,所以把操作流程以及一些用到的類和方法記錄一下。
目錄
1.UI界面制作
2.加入播放器類
3.播放器初始化
4.功能控件
? ? ? ? 4.1 播放、暫停、切換歌曲
? ? ? ? ?4.2 添加、刪除、清空
? ? ? ? 4.3 音量控制
? ? ? ? 4.4 進(jìn)度條
5. 總結(jié)
1.UI界面制作
? ? ? ? 作為一個(gè)音樂播放器,最基礎(chǔ)的肯定就是播放、暫停、上一首以及下一首,為了使這個(gè)界面好看一點(diǎn),還加入了音量控制、進(jìn)度條、歌曲列表等內(nèi)容,至于這種配色和效果好不好看,我也不知道,個(gè)人審美一如既往的不達(dá)標(biāo)。
? ? ? ? ?QT設(shè)計(jì)界面有兩種方式,一種是直接通過純代碼的方式實(shí)現(xiàn),將各種控件以及布局通過代碼的方式編排成一個(gè)完整的UI界面,但是這種方式較為麻煩也比較復(fù)雜,代碼量也比較大,還有一種就是通過UI文件拖拽QT控件,來對(duì)整個(gè)布局進(jìn)行排版的效果,我這里為了省事采用的就是這種方式,至于實(shí)際效果怎么樣那就要看個(gè)人審美了。
? ? ? ? 整個(gè)UI界面內(nèi)部使用到的基礎(chǔ)控件有以下幾種:
控件名稱 | 控件類 | 控件功能 |
---|---|---|
ToolButton? | QToolButton | 用來控制暫停、播放、切換歌曲的功能 |
PushButton | QPushButton | 用來控制添加、刪除、清空歌曲列表的功能 |
horizontalSlider | QSlider | 用來控制播放進(jìn)度、音量等功能 |
listWidget | QListWidget | 歌單列表,內(nèi)部存入添加的歌曲 |
groupBox | QgroupBox | 內(nèi)部放入播放列表 |
label | Qlabel | 標(biāo)簽,可以用來顯示提示信息以及圖片 |
????????
2.加入播放器類
? ? ? ? UI界面設(shè)計(jì)完成之后就是加入播放器類。QT中使用播放器類需要加入對(duì)應(yīng)的鏈接模塊,通過查詢QT的幫助手冊(cè)可以查到,然后在項(xiàng)目的pro文件中加上即可。
? ? ? ? ?加入鏈接模塊后,需要添加我們需要使用到的一些相關(guān)的播放器類頭文件
#include <QMediaPlayer> //播放器類
#include <QMediaPlaylist> //播放器列表類
3.播放器初始化
? ? ? ? 我們的播放器和播放器列表從創(chuàng)建、使用、以及最后程序結(jié)束的釋放都是同一個(gè),這樣有禮物我們對(duì)于整個(gè)播放器的管理,所以我們要保證初始化時(shí)創(chuàng)建的播放器在我們的程序運(yùn)行階段一直存在而不會(huì)應(yīng)該哪個(gè)程序結(jié)束而被釋放掉,所以我們要在界面類的成員中添加播放器和播放器列表。
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
void Music_Init(); //音樂播放器初始化函數(shù)
public slots:
private:
Ui::Widget *ui;
QMovie * Music_GIF; //GIF動(dòng)態(tài)圖片(就是封面上的周杰倫的那個(gè)圖片)
QMediaPlayer *my_Player; //播放器類成員
QMediaPlaylist *my_PlayerList; //播放器列表類成員
};
? ? ? ? ?這里的Music_GIF成員是用來設(shè)置動(dòng)態(tài)圖片的,因?yàn)槲覀冊(cè)诤竺娴脑O(shè)計(jì)中,需要按下暫停鍵可以暫停GIF所以加入了這個(gè)成員。
void Widget::Music_Init()
{
Music_GIF = new QMovie(":/圖標(biāo)資源/周杰倫GIF.gif");
my_Player = new QMediaPlayer;
my_PlayerList =new QMediaPlaylist;
my_Player->setPlaylist(my_PlayerList); //設(shè)置播放列表
my_PlayerList->setPlaybackMode(QMediaPlaylist::Loop); //設(shè)置播放模式
//如果需要初始化時(shí)播放列表中就存在歌曲可以加入下面的代碼
//如果沒有需要可以暫時(shí)不加
QList<QUrl> Url; //創(chuàng)建一個(gè)鏈接列表
QUrl url = QUrl::fromLocalFile("E:\\QT\\QT_Widget\\SmartHome\\音頻資源\\愛在西元前-周杰倫.mp3"); //可以自動(dòng)讀取到指定目錄下的歌曲,加入到鏈接列表中
for(auto url_list : Url) //通過循環(huán)的方式,把鏈接列表添加到播放列表中
{
ui->listWidget->addItem(url_list.fileName()); //添加到UI界面中的listWidget中
my_PlayerList->addMedia(QMediaContent(url_list)); //添加到播放器列表中
}
}
4.功能控件
? ? ? ? 對(duì)于功能的設(shè)計(jì)無非就是通過代碼來實(shí)現(xiàn)你所設(shè)計(jì)的這些控件的基本功能。
? ? ? ? 4.1 播放、暫停、切換歌曲
?????????這一功能我采用的是三個(gè)ToolButoon來控制的,pushButoon按鈕和toolButton按鈕的使用方式是一樣的,但是toolButton可以設(shè)置Icon,即可以讓按鈕顯示圖標(biāo),而不影響其內(nèi)部的Text文本,pushButton按鈕沒有Icon設(shè)置,只能是文字形式,這個(gè)地方我的表達(dá)可能不是很清楚,但是大家動(dòng)手實(shí)驗(yàn)一下應(yīng)該就可以明白了。
????????設(shè)置好按鈕后就可以開始搭建功能,首先是連接好按鈕的信號(hào)與槽函數(shù)。主要有兩種方式,我使用的是第二種,大家可以自行選擇。
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
Music_Init();
/******************************* 方式一 ***********************************/
//設(shè)置按鈕來控制播放器的播放、暫停、切換等功能可以直接使用播放器類中自帶的槽函數(shù)
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()));
//在本設(shè)計(jì)中暫停按鍵沒有,是通過改變播放按鍵的功能來實(shí)現(xiàn)的暫停,如果大家需要一個(gè)按鍵單獨(dú)控制暫??梢允褂孟路胶瘮?shù)
connect(ui->toolButton_pause,SIGNAL(clicked(bool)),my_Player,SLOT(play()));
/******************************* 方式二 ***********************************/
//因?yàn)槲疫@里按下按鈕之后需要控制按鈕的圖標(biāo)改變,所以這里沒有直接鏈接到播放器的槽函數(shù),而是自己寫的一個(gè)槽函數(shù)
//播放按鈕
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()));
//兩種方式選擇一種即可,這里我采用的是第二種方式。
}
使用的第二種方式的話槽函數(shù)需要自己寫出來,下面就是我的整個(gè)槽函數(shù)的設(shè)置。
void Widget::slot_toolButton_Music_Contrl()
{
QToolButton * button = (QToolButton *)sender(); //獲取當(dāng)前按鍵
if(my_PlayerList->isEmpty() == false) //判斷當(dāng)前播放列表是否為空
{
ui->listWidget->setCurrentRow(0); //設(shè)置自動(dòng)選擇第一首歌
if(button->text() == "播放") //判斷當(dāng)前按鍵是否為播放
{
int index = my_PlayerList->currentIndex(); //獲取當(dāng)前歌曲的下標(biāo)
QListWidgetItem *Song_Item =ui->listWidget->item(index); //獲取當(dāng)前播放歌曲的歌名
QString song_name = Song_Item.text();
//將當(dāng)前歌名存入song_name中,因?yàn)槲覜]有設(shè)置這個(gè)控件,所以這里并不使用這個(gè)變量,若大家需要可以參考,自行設(shè)置
Music_GIF->start(); //播放封面GIF
my_Player->play(); //播放歌曲
ui->toolButton_play->setIcon(*music_contrl_pause); //修改播放按鍵設(shè)置,使其下一次的功能改為暫停
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的狀態(tài)
}else
{
//此功能需要加入頭文件 #include <QMessageBox>
QMessageBox::warning(this,"播放失敗","未找到音頻文件"); //提示會(huì)話彈窗
}
}
? ? ? ? ?4.2 添加、刪除、清空
? ? ? ? ?添加、刪除、清空這三個(gè)按鍵的話,就沒有前面的播放那些按鍵那么復(fù)雜,不需要考慮太多的美觀問題,只需要實(shí)現(xiàn)功能即可。首先也是需要先連接到信號(hào)槽
? ? ? ? 在這里我寫一個(gè)另外的方式來實(shí)現(xiàn)槽函數(shù)的連接,那就是UI界面中的轉(zhuǎn)到槽功能
?????????通過轉(zhuǎn)到槽的方式,QT會(huì)自動(dòng)聲明和定義空槽函數(shù),并將對(duì)應(yīng)的按鍵連接到此槽函數(shù),我們只需要在空的槽函數(shù)中填入代碼就可以實(shí)現(xiàn)基本功能。
void Widget::on_toolButton_add_music_clicked() //新增按鍵槽函數(shù)
{
//這個(gè)功能需要加入兩個(gè)頭文件 #include <QFile>
// #include <QFileDialog>
QList<QUrl> play_list = QFileDialog::getOpenFileUrls(this,"添加音樂"); //添加音樂
//這串代碼會(huì)打開一個(gè)文件會(huì)話窗口,我們可以選擇其中的音頻文件,QT會(huì)以u(píng)rl鏈接的形式填入列表中
for(auto musiclist : play_list) //通過循環(huán)插入
{
my_PlayerList->addMedia(QMediaContent(musiclist)); //插入播放列表
ui->listWidget->addItem(musiclist.fileName()); //插入listWidget列表
}
}
void Widget::on_toolButton_delete_music_clicked() //刪除按鍵槽函數(shù)
{
int row = ui->listWidget->currentRow(); //獲取當(dāng)前指針?biāo)谛? if(row != -1)
{
ui->listWidget->takeItem(row); //從列表界面中刪除
my_PlayerList->removeMedia(row); //從播放器列表中刪除
Music_GIF->stop(); //停止播放GIF
ui->label_GIF->setMovie(Music_GIF); //刷新GIF狀態(tài)
}
}
void Widget::on_toolButton_clear_music_clicked() //清空按鍵槽函數(shù)
{
ui->listWidget->clear(); //清空listWidget控件
my_Player->stop(); //停止播放歌曲
Music_GIF->stop(); //停止播放GIF
ui->label_GIF->setMovie(Music_GIF); //刷新GIF狀態(tài)
my_PlayerList->clear(); //清空播放列表
ui->toolButton_play->setIcon(*music_contrl_play); //修改播放按鍵圖標(biāo)
ui->toolButton_play->setText("播放"); //修改播放按鍵名稱
}
以上就是添加、刪除、清空的實(shí)現(xiàn)代碼。
? ? ? ? 4.3 音量控制
????????音量控制使用的是水平滑塊來實(shí)現(xiàn)
//在播放器類中,自帶有設(shè)置播放音量的槽函數(shù),我們只需要將滑塊控件鏈接到槽即可。
//當(dāng)水平滑塊的值發(fā)生改變時(shí),發(fā)送信號(hào)
connect(ui->horizontalSlider_volume,SIGNAL(valueChanged(int)),my_Player,SLOT(setVolume(int)));
? ? ? ? 為了更加人性化以及美觀,在音量控制這一塊,我還加入了圖標(biāo)的變化,通過不同的音量控制不同的圖標(biāo)。
? ? ? ? ?首先也是連接到槽函數(shù),這里的話一個(gè)信號(hào)是可以連到多個(gè)槽函數(shù),一個(gè)槽函數(shù)也可以有多個(gè)信號(hào)觸發(fā),所以這邊我們?cè)偻ㄟ^音量的水平滑塊來控制圖標(biāo)變化。
//當(dāng)水平滑塊值發(fā)生改變時(shí)觸發(fā)
connect(ui->horizontalSlider_volume,SIGNAL(valueChanged(int)),this,SLOT(solt_horizontalSlider_volume_Icon(int)));
? ? ? ? ?槽函數(shù)如下:
void Widget::solt_horizontalSlider_volume_Icon(int value)
{
QPixmap *Mute = new QPixmap(":/圖標(biāo)資源/靜音.png"); //添加圖標(biāo)資源
QPixmap *small = new QPixmap(":/圖標(biāo)資源/音量小.png");
QPixmap *middle = new QPixmap(":/圖標(biāo)資源/音量中.png");
QPixmap *big = new QPixmap(":/圖標(biāo)資源/音量大.png");
if(value == 0) //值為0
{
ui->label_volume->setPixmap(*Mute); //圖標(biāo)為靜音
}else if(value <= 33)
{
ui->label_volume->setPixmap(*small ); //圖標(biāo)為小音量
}else if(value <= 66)
{
ui->label_volume->setPixmap(*middle); //圖標(biāo)為中音量
}else if(value <= 100)
{
ui->label_volume->setPixmap(*big ); //圖標(biāo)為大音量
}
}
? ? ? ? ?在UI設(shè)計(jì)時(shí),初始的滑塊樣式是這個(gè)樣子的
?改變其樣式表可以改成我上面的那種樣子,樣式表代碼如下:
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;
}
通過這些設(shè)置基本上音量控制也弄的差不多了。
? ? ? ? 4.4 進(jìn)度條
? ? ? ? 進(jìn)度條的UI設(shè)置主要有兩個(gè)控件,一個(gè)是顯示的當(dāng)前播放進(jìn)度、總時(shí)長(zhǎng)的Qlabel控件、一個(gè)是顯示當(dāng)前進(jìn)度的水平滑塊控件。
?????????播放進(jìn)度的設(shè)置,需要通過兩個(gè)QMediaPlayer類中的函數(shù)來實(shí)現(xiàn),通過查詢QT的幫助手冊(cè),找到了這兩個(gè)函數(shù)的基本信息。
?這個(gè)函數(shù)可以獲取到當(dāng)前播放媒體的總時(shí)長(zhǎng),它的返回值是一個(gè)qint64的毫秒值。
?這個(gè)函數(shù)的作用是返回當(dāng)前播放媒體的當(dāng)前播放進(jìn)度,返回值也是一個(gè)qint64的毫秒值。
? ? ? ? 這兩個(gè)函數(shù)都有一個(gè)自帶的信號(hào),分別是:
? ? ? ? ?durationChanged信號(hào)在我們切換到一個(gè)新媒體文件的時(shí)候會(huì)發(fā)送一個(gè)信號(hào),并發(fā)送新切換到的媒體的總時(shí)長(zhǎng),也是一個(gè)qint64的毫秒值,我們可以通過槽函數(shù)接收這個(gè)值。
? ? ? ? ?positionChanged信號(hào)是在我們的當(dāng)前播放進(jìn)度發(fā)生改變的時(shí)候會(huì)觸發(fā)的一個(gè)信號(hào),它會(huì)發(fā)送一個(gè)當(dāng)前媒體的當(dāng)前播放進(jìn)度,是一個(gè)qint64的毫秒值,通過槽函數(shù)接收這個(gè)值。
有了以上的函數(shù)介紹,我們基本上可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的進(jìn)度條功能。
//當(dāng)前播放進(jìn)度改變的信號(hào)
connect(my_Player,SIGNAL(positionChanged(qint64)),this,SLOT(slot_positionchange(qint64)));
//播放媒體切換改變的信號(hào)
connect(my_Player,SIGNAL(durationChanged(qint64)),this,SLOT(slot_durationChanged(qint64)));
//拖動(dòng)進(jìn)度條改變播放進(jìn)度
connect(ui->horizontalSlider_Playbac_progress,SIGNAL(valueChanged(int)),this,SLOT(slot_valueChanged_progress(int)));
? ? ? ? 通過槽函數(shù)來實(shí)現(xiàn)其基本功能,槽函數(shù)如下:
//當(dāng)前進(jìn)度改變槽函數(shù)
void Widget::slot_positionchange(qint64 value)
{
//獲取到歌曲總時(shí)長(zhǎng)
ui->horizontalSlider_Playbac_progress->setMaximum(my_Player->duration()/1000);// 設(shè)置進(jìn)度條最大長(zhǎng)度為總時(shí)長(zhǎng)
ui->horizontalSlider_Playbac_progress->setValue(value/1000);//設(shè)置進(jìn)度條的當(dāng)前位置
//QTimer類需要引入頭文件#include <QTimer>
QTime time(0,(value/60000),(value/1000)%60); //將毫秒數(shù)轉(zhuǎn)換成時(shí)間格式
ui->label_now->setText(time.toString("mm:ss")); //將時(shí)間按照指定格式放入Qlabel標(biāo)簽中
}
//當(dāng)前媒體總時(shí)長(zhǎng)改變槽函數(shù)
void Widget::slot_durationChanged(qint64 value)
{
QTime time(0,(value/60000)%60,(value/1000)%60); //將收到的總時(shí)長(zhǎng)轉(zhuǎn)換成時(shí)間格式
ui->label_max->setText(time.toString("mm:ss")); //將時(shí)間放入到指定標(biāo)簽中
}
//進(jìn)度條滑塊數(shù)值改變槽函數(shù)
void Widget::slot_valueChanged_progress(int value)
{
my_Player->setPosition(value*1000); //設(shè)置播放器的當(dāng)前進(jìn)度
}
到這里基本上播放器的進(jìn)度條設(shè)置就實(shí)現(xiàn)完成了。
5. 總結(jié)
? ? ? ? 到這里基本是一個(gè)簡(jiǎn)單的音樂播放器就基本實(shí)現(xiàn)了,雖然里面有很多功能寫的不是很詳細(xì),也有一部分操作我沒有做,但是基本能實(shí)現(xiàn)播放、暫停、切換等基本功能。
? ? ? ? 如果后期需要對(duì)播放器的功能進(jìn)行添加可以自行添加,比方說,QT有自帶的視頻播放功能,可以將中間的GIF圖片換成播放歌曲的MV,還可以添加一個(gè)comboBox控件來選擇當(dāng)前播放器的播放模式,QT有內(nèi)置的宏可以直接設(shè)置,我這里是直接選擇的循環(huán)播放。
? ? ? ? 還有就是好像可以實(shí)現(xiàn)從網(wǎng)絡(luò)獲取歌曲的方法,這種的話就可以不用提前下載好歌曲了,大家可以自己去找一下,不要問我為什么沒做這種,問就是我是菜雞,我不會(huì)。文章來源:http://www.zghlxwxcb.cn/news/detail-423565.html
? ? ? ? 好了,差不多到這里也要結(jié)束了,作為一個(gè)QT的初學(xué)者,里面有很多設(shè)置方法在各位大佬看來可能很笨,但是目前就只有這種水平了,而且大家如果對(duì)各種基礎(chǔ)控件的樣式不滿意,可以去自己找一下各種樣式表,自己設(shè)置一下,我這里就沒有做太多這種操作了。文章來源地址http://www.zghlxwxcb.cn/news/detail-423565.html
到了這里,關(guān)于QT 離線音樂播放器的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!