zoukankan      html  css  js  c++  java
  • C++ QT 音乐播放器

    大一下学期c++课程设计,做了个仿酷狗的音乐播放器。

    整体做的比较粗略,现在大三看还远远不足。

    软件环境:

    Win8+QT5.21+Qt creator 3.01

    需求分析:

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

    组成控件

    功能

    播放/暂停按钮

    播放当前音乐文件或者暂停播放

    上一首按钮

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

    下一首按纽

    播放列表中当前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
  • 相关阅读:
    简明python教程五----数据结构
    简明python教程四-----模块
    简明python教程三-----函数
    简明python教程二-----对象
    linux命令行与shell脚本编程 -----15控制脚本
    14.7创建临时文件
    js --- return返回值 闭包
    js --- 事件流
    git --- ! [rejected] master -> master (non-fast-forward)
    html --- bootstrap 框架 (栅格系统布局)
  • 原文地址:https://www.cnblogs.com/linkarl/p/4802351.html
Copyright © 2011-2022 走看看