C++ QT 音樂播放器

大一下學期c++課程設計,作了個仿酷狗的音樂播放器。c++

總體作的比較粗略,如今大三看還遠遠不足。app

 

軟件環境:

Win8+QT5.21+Qt creator 3.01less

 

需求分析:

:表 1 播放器控件的主要組成部分dom

組成控件ide

功能函數

播放/暫停按鈕oop

播放當前音樂文件或者暫停播放測試

上一首按鈕ui

播放列表中當前MP3文件的上一首MP3文件this

下一首按紐

播放列表中當前MP3文件的下一首MP3文件

打開按鈕

選擇一首MP3文件

列表按鈕

顯示隱藏播放列表窗口

歌詞按鈕

顯示隱藏歌詞顯示窗口

靜音按鈕

打開/關閉播放器的輸出聲音

音量控制條

對播放器的音量大小進行調節

進度控制條

對當前播放的MP3文件的播放進度進行調節

歌名顯示

對當前播放的MP3歌名顯示

歌曲時間顯示

對當前播放的MP3文件的播放時間與總時長顯示

播放模式

對歌曲的播放模式進行選擇

最小化,關閉

把窗口最小化,關閉窗口

 

界面設計:

                        

 

不足:

1)     歌詞功能未能實現

2)     定位功能未能實現

3)     進度與音量必須拖動slider,不然無響應

4)     歌名過長時,歌曲播放列比例不一致

5)     當鼠標通過功能按鈕時,圖標無變化

6)     關閉窗口出現中文沒法支持錯誤,沒法解決,改用英文。

 

代碼:

main.cpp

#include "dialog.h"
#include <QtWidgets/QApplication>
#include <QDesktopWidget>

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    Dialog w;
    w.setWindowFlags(Qt::FramelessWindowHint);//去掉窗口標題欄
    w.show();
    //將窗口放置在屏幕靠左,獲取屏幕的高-窗體的高除以2.
    w.move(((QApplication::desktop()->width()-w.width())*0.25),
           (QApplication::desktop()->height()-w.height())>>1);
    return a.exec();
}

 

dialog.cpp

#include "dialog.h"
#include "ui_dialog.h"
#include "QMediaPlayer"
#include "QFile" //一個操做文件的輸入/輸出設備
#include "QDir"
#include "QFileDialog"
#include "QMediaPlaylist"
#include "QTime"
#include <QMessageBox>
#include <QDebug> //測試用

Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)//,lrcUi(new Ui::lrcDialog)
{

    playList=new QMediaPlaylist;
    player =new QMediaPlayer;
    ui->setupUi(this);
    ui->progressBar->setRange(0,0);//初始化進度條,範圍0到0,進度條沒法拖動
    ui->songList->setColumnWidth(0,200);//初始化歌曲列表的列寬
    ui->songList->setRowHeight(0,60);//初始化歌曲列表的行寬
    ui->findFrame->hide();//查找窗口默認隱藏

    /*
     * 播放模式選擇的菜單
     */
    currentItemInLoop = new QAction(tr("單曲循環"), this);
    sequential = new QAction(tr("順序播放"), this);
    loop = new QAction(tr("列表循環"), this);
    random = new QAction(tr("隨機播放"), this);
    model = new QMenu(tr("播放模式"),this);
    model->addAction(currentItemInLoop);
    model->addAction(sequential);
    model->addAction(loop);
    model->addAction(random);

    playSong= new QAction(tr("播放"), this);
    connect(playSong, SIGNAL(triggered()), this, SLOT(on_play_clicked()));
    stopSong= new QAction(tr("暫停"), this);
    connect(stopSong, SIGNAL(triggered()), this, SLOT(on_play_clicked()));
    nextSong= new QAction(tr("下一音樂"), this);
    connect(nextSong, SIGNAL(triggered()), this, SLOT(on_nextSong_clicked()));
    previousSong= new QAction(tr("上一音樂"), this);
    connect(previousSong, SIGNAL(triggered()), this, SLOT(on_firstSong_clicked()));

    /*
     * 托盤圖標的右鍵菜單
     */
    trayIcon = new QSystemTrayIcon(this);
    trayMenu = new QMenu(this);
    trayIcon->setIcon(QIcon(":/images/tray.png"));
    minimizeAction = new QAction(tr("最小化"), this);
    connect(minimizeAction, SIGNAL(triggered()), this, SLOT(hide()));
    quitAction = new QAction(tr("關閉程序"), this);
    connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
    trayMenu->addAction(playSong);
    trayMenu->addAction(stopSong);
    trayMenu->addAction(nextSong);
    trayMenu->addAction(previousSong);
    trayMenu->addSeparator();
    trayMenu->addMenu(model);
    trayMenu->addSeparator();
    trayMenu->addAction(minimizeAction);
    trayMenu->addAction(quitAction);
    trayIcon->show();
    trayIcon->setContextMenu(trayMenu);
    //托盤圖標添加單/雙擊鼠標相應
    connect(trayIcon,SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
            this,SLOT(trayiconActivated(QSystemTrayIcon::ActivationReason)));


    /*
     * 歌曲列表的右鍵菜單
     */
    songMenu= new QMenu(this);
    addSong= new QAction(tr("添加歌曲"), this);
    connect(addSong, SIGNAL(triggered()), this, SLOT(on_open_clicked()));
    delSong= new QAction(tr("刪除歌曲"), this);
    connect(delSong, SIGNAL(triggered()), this, SLOT(delMusic()));
    clearList= new QAction(tr("清空播放列表"), this);
    connect(clearList, SIGNAL(triggered()), this, SLOT(clearMusic()));
    songMenu->addAction(playSong);
    songMenu->addAction(addSong);
    songMenu->addAction(delSong);
    songMenu->addAction(clearList);
    ui->songList->setContextMenuPolicy(Qt::CustomContextMenu);



    //add="D:/QTWLXI/Music1/MUSIC/sor/咱們的歌.mp3";// test
    //player->setMedia(QUrl::fromLocalFile(add));// test

    player->setPlaylist(playList);//設置相應playlist
    player->setVolume(100);//設置初始化音量
    isSilence=false;//默認不靜音
    isPlay=false;//默認不播放歌曲
    isOpenLyric=true;//默認打開歌詞

    //進度條改變時播放位置隨着改變
    connect(ui->progressBar,SIGNAL(sliderMoved(int)),this,SLOT(setPlayerPosition(int)));
    //當播放歌曲位置改變時  progressBar設置對應的位置 對應的播放時間與總時間的顯示
    connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(positionChanged(qint64)));
    // 當progressBar改變時  構造歌曲總時間
    connect(player, SIGNAL(durationChanged(qint64)), this, SLOT(durationChanged(qint64)));
    //songList 雙擊播放選中的
    connect(ui->songList,SIGNAL(cellDoubleClicked(int,int)),this,SLOT(playto(int,int)));
    //顯示歌名
    connect(playList,SIGNAL(currentIndexChanged(int)),this,SLOT(showSongName(int)));
    // connect(playList,SIGNAL(currentIndexChanged(int)),this,SLOT(showLyric(int)));

    //播放模式設置
    /*   信號無參數的狀況下,沒法直接給槽傳入參數,次方法違背信號與槽參數一致,解決方法在下面
     *  connect(currentItemInLoop, SIGNAL(triggered()), this, SLOT(setPlayModel(0)));
    connect(sequential, SIGNAL(triggered()), this, SLOT( setPlayModel(1)));
    connect(loop, SIGNAL(triggered()), this, SLOT( setPlayModel(2)));
    connect(random, SIGNAL(triggered()), this, SLOT( setPlayModel(3))); */
    //讓action響應相應的model槽,讓model槽設置相應信號selectedModel的參數在傳給setPlayModel
    connect(this, SIGNAL(selectedModel(int)), this, SLOT( setPlayModel(int)));
    connect(this, SIGNAL(selectedModel(int)), this, SLOT( setPlayModel(int)));
    connect(this, SIGNAL(selectedModel(int)), this, SLOT( setPlayModel(int)));
    connect(this, SIGNAL(selectedModel(int)), this, SLOT( setPlayModel(int)));
    connect(currentItemInLoop, SIGNAL(triggered()), this, SLOT( model0()));
    connect(sequential, SIGNAL(triggered()), this, SLOT( model1()));
    connect(loop, SIGNAL(triggered()), this, SLOT( model2()));
    connect(random, SIGNAL(triggered()), this, SLOT( model3()));

}

void Dialog::model0()
{
    emit selectedModel(0);
}
void Dialog::model1()
{
    emit selectedModel(1);
}
void Dialog::model2()
{
    emit selectedModel(2);
}
void Dialog::model3()
{
    emit selectedModel(3);
}

Dialog::~Dialog()
{
    delete ui;
}

/*
 *  刪除歌曲
 */
void Dialog::delMusic(){
    static int b=0;
    if (QMessageBox::Yes == QMessageBox::question(this,
                                                  tr("Question"),
                                                  tr("Sure you want to delete this song?"),
                                                  QMessageBox::Yes | QMessageBox::No,
                                                  QMessageBox::Yes)) {
        int i=ui->songList->currentRow();
        playList->clear();
        ui->songList->clear();
        songName.removeAt(i);
        qDebug()<<i<<endl;
        QString s = QString::number(i, 10);
        for(int j=0;j<songName.length();j++)
        ui->songList->setItem(++b, 0, new QTableWidgetItem(s+" "+songName[i]));
        ui->strTime->setText("00:00");
        QMessageBox::information(this, tr("information"), tr("刪除成功"));
    } else {
        QMessageBox::information(this,tr("information"),tr("取消刪除"));
    }

}
/*
 *  清空列表
 */
void Dialog::clearMusic(){
    playList->clear();
    ui->songList->clear();
    ui->songList->setRowCount(0);
    ui->strTime->setText("00:00");
}


/*
 *  音量調節
 */
void Dialog::on_volume_sliderMoved(int position)
{
    player->setVolume(position);
    ui->volume->setValue(position);

    if(position==0){
        ui->silence->setIcon(QIcon(":/images/silence.png"));
        isSilence=true;
    }else{
        ui->silence->setIcon(QIcon(":/images/nosilence.png"));
        isSilence=false;
    }
}

/*
 *  靜音及恢復
 */
void Dialog::on_silence_clicked()
{
    isSilence=!isSilence;
    if(isSilence)
    {
        volumeValue=ui->volume->value();
        on_volume_sliderMoved(0); //記錄靜音前的音量
        ui->silence->setIcon(QIcon(":/images/silence.png"));
    }
    else
    {
        on_volume_sliderMoved(volumeValue);//恢復靜音前的音量
        ui->silence->setIcon(QIcon(":/images/nosilence.png"));
    }
}


/*
 *  添加歌曲
 */
void Dialog::on_open_clicked()
{
    QString initialName=QDir::homePath();//在window下返回用戶(即個人文檔)目錄
    //getOpenFileNames(指定父組件,對話框的標題,默認打開的目錄,後綴名過濾器,若是須要使用多個過濾器 使用";;"分割
    // ,是默認選擇的過濾器,對話框的一些參數設定,好比只顯示文件夾等等,)
    QStringList pathList=QFileDialog::getOpenFileNames(this, tr("選擇文件"), initialName, tr("MP3 Files (*.mp3)"));
    //用一個QStringList列表 存放音樂文件的地址,可多選音樂。
    for(int i=0; i<pathList.size(); ++i)
    {
        QString path=QDir::toNativeSeparators(pathList.at(i));//把斜槓轉化成反斜槓,獲取歌曲的地址

        if(!path.isEmpty())
        {
            playList->addMedia(QUrl::fromLocalFile(path));
            //QUrl::fromLocalFile()必定要用這個方法,由於若是文件名或路徑有中文或空格,就打不開文件.
            //直接用QUrl(fileName)只能打開英文名稱和沒有空格路徑的文件.
            QString fileName=path.split("\\").last();//用split 獲取文件名(包含後綴) 例 music.mp3
            int rownum=ui->songList->rowCount();//行數
            ui->songList->insertRow(rownum);//插入空行
            QString s = QString::number(ui->songList->rowCount(), 10);
            QString Name=fileName.split(".").front();
            ui->songList->setItem(rownum, 0, new QTableWidgetItem(s+" . "+Name));
            songName.append(Name);
        }
    }
}

/*
 *  下一曲
 */
void Dialog::on_nextSong_clicked()
{
    //若是播放列表爲空,按鈕不可用,直接返回
    if(playList->isEmpty())
        return;
    //若是列表到盡頭,則回到列表開頭
    int currentIndex=playList->currentIndex();
    if(++currentIndex==playList->mediaCount())
        currentIndex=0;
    //設置當前的currentIndex
    playList->setCurrentIndex(currentIndex);
    isPlay=true;
    on_play_clicked();
}

/*
 *  上一曲
 */
void Dialog::on_firstSong_clicked()
{
    //播放列表爲空,按鈕不可用,直接返回
    if(playList->isEmpty())
        return;
    //若是列表到開頭,則中止播放,直接返回
    int currentIndex=playList->currentIndex();
    if(currentIndex==0){
        isPlay=false;
        on_play_clicked();
        return;
    }
    playList->previous();
    isPlay=true;
    on_play_clicked();
}

/*
 *  播放和暫停
 */
void Dialog::on_play_clicked()
{
    //若是播放列表爲空,按鈕不可用,直接返回
    if(playList->isEmpty())
        return;
    isPlay=!isPlay;

    if(isPlay)
    {   player->pause();
        ui->play->setIcon(QIcon(":/images/play.png"));// 暫停時候顯示播放圖標
        ui->play->setToolTip(tr("暫停"));
    }
    else
    {   player->play();
        ui->play->setIcon(QIcon(":/images/pause.png"));// 播放時候顯示暫停圖標
        ui->play->setToolTip(tr("播放"));
    }
}

/*
 *  當進度條改變時,設置歌曲對應的播放位置
 */
void Dialog::setPlayerPosition(int position)
{
    player->setPosition(position);
}

/*
 *  當播放歌曲位置改變時  progressBar設置對應的位置 對應的播放時間與總時間的顯示
 */
void Dialog::positionChanged(qint64 position)//
{
    ui->progressBar->setValue(position);//position 單位:毫秒 1000ms=1s
    currentTime=new QTime(0,(position/60000)%60,(position/1000)%60);//構造當前時間(小時,分鐘,秒和毫秒)。
    ui->strTime->setText(currentTime->toString("mm:ss"));//播放時間   輸出時間格式09:02(都是兩位)
}

/*
 *  當progressBar改變時  構造歌曲總時間
 */
void Dialog::durationChanged(qint64 duration)//
{
    ui->progressBar->setRange(0,duration);//progressBar的範圍從0到duration(總時間)
    totalTime=new QTime(0,(duration/60000)%60,(duration/1000)%60);
    ui->endTime->setText(totalTime->toString("mm:ss"));//歌曲總時間
}

/*
 *  當雙擊songList時 播放雙擊的歌曲
 */
void Dialog::playto(int i,int )
{
    playList->setCurrentIndex(i);
    isPlay=true;
    on_play_clicked();
}

/*
 *  當前播放歌曲名顯示
 */
void Dialog::showSongName(int i)
{
    ui->songList->selectRow(i);   //播放到這首歌曲的時候選中
    QString playtitle=songName[i];
    ui->showSongName->setText(playtitle);
}

/*
 *   設置播放方式 QMediaPlaylist::PlaybackMode
 */
void Dialog::setPlayModel(int i)
{
    switch (i)
    {
    case 0:
        playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);//單曲循環
        ui->playModel->setIcon(QIcon(":/images/CurrentItemInLoop.png"));
        ui->playModel->setToolTip(tr("單曲循環"));
        break;
    case 1:
        playList->setPlaybackMode(QMediaPlaylist::Sequential);//順序播放
        ui->playModel->setIcon(QIcon(":/images/Sequential.png"));
        ui->playModel->setToolTip(tr("順序播放"));
        break;
    case 2:
        playList->setPlaybackMode(QMediaPlaylist::Loop);//列表循環
        ui->playModel->setIcon(QIcon(":/images/Loop.png"));
        ui->playModel->setToolTip(tr("列表循環"));
        break;
    case 3:
        playList->setPlaybackMode(QMediaPlaylist::Random);//隨機播放
        ui->playModel->setIcon(QIcon(":/images/Random.png"));
        ui->playModel->setToolTip(tr("隨機播放"));
        break;
    }
}

/*
 *  模擬標題欄移動消息,使之能夠移動
 */
void Dialog::mousePressEvent(QMouseEvent *event)
{
    if (ReleaseCapture())
        SendMessage(HWND(this->winId()), WM_SYSCOMMAND, SC_MOVE + HTCAPTION, 0);
    event->ignore();
}

/*
 *  窗口最小化
 */
void Dialog::on_minWindow_clicked()
{
    //系統自定義的最小化窗口函數
    showMinimized();
    //最大化 showMaximized();
}

/*
 *  窗口關閉
 */
void Dialog::on_closeWindow_clicked()
{
    //系統自定義的窗口關閉函數
    close();
}

/*
 *  處理關閉事件
 */
void Dialog::closeEvent(QCloseEvent *event)
{
    QMessageBox::StandardButton button;
    button = QMessageBox::question(this,tr("Exit the program"),
                                   tr("Do you really want to exit the program"),
                                   QMessageBox::Yes|QMessageBox::No);

    if (button == QMessageBox::No) {
        event->ignore();  //忽略退出信號,程序繼續運行
    }
    else if (button == QMessageBox::Yes) {
        event->accept();  //接受退出信號,程序退出
    }
}

/*
 *  播放模式的菜單
 */
void Dialog::on_playModel_clicked()
{
    QPoint pos(this->x()+47,this->y()+91);//播放模式菜單起點座標
    model->exec(pos);//讓播放模式菜單在固定的點顯示
}

void Dialog::trayiconActivated(QSystemTrayIcon::ActivationReason reason)
{
    if(reason==QSystemTrayIcon::Trigger||QSystemTrayIcon::DoubleClick){
        this->showNormal();
        this->raise();
    }
}


/*
 *  歌曲列表右鍵菜單
 */
void Dialog::on_songList_customContextMenuRequested(const QPoint &pos)
{
    songMenu->exec(QCursor::pos());
}

/*
 *  顯示查找窗口
 */
void Dialog::on_find_clicked()
{
    ui->findFrame->show();
}

/*
 *  關閉查找窗口
 */
void Dialog::on_close_clicked()
{
    ui->findFrame->hide();

}

/*
 *  查找功能
 */
void Dialog::on_enter_clicked()
{
    QString song=ui->lineEdit->text();
    static int a=0;
    for(int i=0;i<songName.length();i++){
        if(songName[i].contains(song)){
            ui->songList->clear();
            ui->songList->setItem(a++, 0, new QTableWidgetItem(songName[i]));
        }
    }

}

/* 方法做廢 只能顯示LRC的所有內容,沒法隨時時間只顯示歌詞
void Dialog::showLyric(int z){

    //顯示歌詞部分
    if(isOpenLyric==true)
    {
        QString str=songName[z];
        qDebug()<<songName[z]<<endl;
        QFile file("C:\\Users\\k\\Desktop\\musicplayer\\Music3.0\\"+str+".lrc");//
        qDebug()<<"C:\\Users\\k\\Desktop\\musicplayer\\Music3.0\\"+str+".lrc"<<endl;
        if(!file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            QMessageBox::information(this, tr("information"), tr("當前目錄下未找到歌詞文件"));
        }
        else
        {
            QTextStream in(&file);
            QString result=in.readAll();
            ui->textEdit->setText(result);
        }
    }
}
void Dialog::on_lyric_clicked()
{
    isOpenLyric=!isOpenLyric;
    if(isOpenLyric==true){
       ui->textEdit->hide();
    }else{
       ui->textEdit->show();
    }
}
*/

void Dialog::on_position_clicked()
{
    //TODO 沒法使用,沒法使當前播放的歌曲被定位
    int i=ui->songList->currentRow();
    ui->songList->visualRow(i);

}

 

dialog.h

#ifndef DIALOG_H
#define DIALOG_H

#include "QDialog"
#include "QtMultimedia"
#include <QCloseEvent>
#include <QMenu>
#include <QSystemTrayIcon>


class QMediaPlaylist;
class QMediaPlayer;


namespace Ui {
class Dialog;
}

class Dialog : public QDialog
{
    Q_OBJECT

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


signals:
    void selectedModel(int);

private slots:

    void on_volume_sliderMoved(int position);

    void on_silence_clicked();

    void on_open_clicked();

    void on_nextSong_clicked();

    void on_firstSong_clicked();

    void on_play_clicked();

    void setPlayerPosition(int);

    void positionChanged(qint64 position);

    void durationChanged(qint64 duration);

    void playto(int,int);

    void showSongName(int );

    void setPlayModel(int);

    void on_closeWindow_clicked();//關閉窗口

    void on_minWindow_clicked();//最小化窗口

    void on_playModel_clicked();

    void delMusic();

    void clearMusic();

    void model0();
    void model1();
    void model2();
    void model3();

    void trayiconActivated(QSystemTrayIcon::ActivationReason reason);


    void on_songList_customContextMenuRequested(const QPoint &pos);

    void on_find_clicked();

    void on_close_clicked();

    void on_enter_clicked();

   //void on_lyric_clicked();

   // void showLyric(int);

    void on_position_clicked();

private:

    Ui::Dialog *ui;

    QStringList songName;
    QMediaPlayer *player;
    QMediaPlaylist *playList;
    bool isSilence;
    bool isPlay;
    bool isOpenLyric;
    QTime *currentTime;
    QTime *totalTime;
    QAction *currentItemInLoop;
    QAction *sequential;
    QAction *loop;
    QAction *random;
    QMenu   *trayMenu;
    QMenu   *model;
    QSystemTrayIcon *trayIcon;
    QAction *playSong;
    QAction *stopSong;
    QAction *nextSong;
    QAction *previousSong;
    QAction *quitAction;
    QAction *minimizeAction;

    QMenu *songMenu;
    QAction *addSong;
    QAction *delSong;
    QAction *clearList;

    int volumeValue;
    void Dialog::mousePressEvent(QMouseEvent *event);
    void closeEvent(QCloseEvent *event);
};


#endif // DIALOG_H
相關文章
相關標籤/搜索