1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > Qt之音乐播放器

Qt之音乐播放器

时间:2020-09-27 20:43:47

相关推荐

Qt之音乐播放器

-2-26,项目耗时:2天

实现的功能

依据歌曲作者对歌曲进行分类,并以树状目录的结构显示在界面上进度条实现播放、暂停、音量调节显示当前歌曲名

效果如下

模块划分

歌曲目录树模块:用来将歌曲文件以目录树的形式展现在界面上,并向外界提供当前被选中歌曲的路径信息。控制面板模块:用来控制播放器的行为,以及反应播放器的状态。播放器模块:播放器引擎,用来执行音乐文件的播放。顶层模块:用来将以上模块组合在一起。

下面一一介绍每个模块的实现。

歌曲目录树模块

主要用到了一个QTreeWidget类,我从这个类派生出一个MusicTreeList类,关于QTreeWidget的详细说明见帮助文档。

music_tree_list.h

#ifndef MUSIC_TREE_LIST_H#define MUSIC_TREE_LIST_H#include "QTreeWidget"class MusicTreeList : public QTreeWidget{Q_OBJECTpublic:MusicTreeList();~MusicTreeList();public slots:void musicChanged(QTreeWidgetItem *item, int column);signals:void currentMusic(QString str);};#endif // MUSIC_TREE_LIST_H

music_tree_list.cpp

#include "music_tree_list.h"#include "QRegExp"#include "QtDebug"#include "QDir"MusicTreeList::MusicTreeList(){//设置歌曲栏目,详细用法见QTreeWidget帮助文档this->setColumnCount(2);QStringList headers;headers << QObject::tr("歌名") << QObject::tr("发行时间");this->setHeaderLabels(headers);//设定音乐文件目录,使用过滤器保留歌曲作者文件夹,详细用法见QDir帮助文档QStringList folder;QString dirPath = "C:/Users/jiage/Desktop/folder/QT/qtreewidget/music";QDir dir(dirPath);dir.setFilter(QDir::Dirs);//foreach语句遍历dir中的文件夹名称列表,与此同时构建对应的目录树foreach(QFileInfo fullDir, dir.entryInfoList()){if(fullDir.fileName() == "." || fullDir.fileName() == "..") continue;folder.push_back(fullDir.fileName());QStringList singer_name;singer_name << fullDir.fileName();QTreeWidgetItem *temp_singer = new QTreeWidgetItem( this, singer_name );QDir temp_dir(fullDir.absoluteFilePath());QStringList nameFilters;nameFilters << "*.mp3";QStringList files = temp_dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name);while( !files.isEmpty() ) {QStringList song_name;song_name << files[0];QTreeWidgetItem *temp_song = new QTreeWidgetItem(temp_singer, song_name);temp_singer->addChild(temp_song);files.pop_front();}}//当QTreeWidget中某个item被点击时,将这个被点击的item所对应的歌曲路径以字符串的形式发送出去connect(this, &QTreeWidget::itemClicked, this, &MusicTreeList::musicChanged);}MusicTreeList::~MusicTreeList(){}void MusicTreeList::musicChanged(QTreeWidgetItem *item, int column){QString music_end_path;QString pattern(".*.mp3");QRegExp rx(pattern);bool match = rx.exactMatch(item->text(column));if ( !match ){return;}music_end_path = "/" + item->parent()->text(column) + "/" + item->text(column);//qDebug() << music_end_path;emit currentMusic( music_end_path );}

总的来说,这个类的作用就是根据用户点击的歌曲,以字符串的形式输出该歌曲的路径。

控制面板模块

ControlPanel类继承自QWidget。

control_panel.h

#ifndef CONTRO_PANEL_H#define CONTRO_PANEL_H#include <QWidget>class QPushButton;class QSlider;class QLabel;class ControlPanel : public QWidget{Q_OBJECTpublic:explicit ControlPanel(QWidget *parent = nullptr);~ControlPanel();QPushButton * stop_btn;//停止QPushButton * last_btn;//上一首QPushButton * next_btn;//下一首QPushButton * play_btn;//播放或者暂停QPushButton * volume_btn;//音量启停QPushButton * orderplay_btn;//顺序播放QSlider * music_progress;//音乐进度滑杆QSlider * volume_slider;//音量滑杆QLabel * time_label;//时间标签QString total_time;//总时间QString current_time;//当前时间public slots:void changeTotalTime(qint64 duration);//歌曲切换时发生void updateProgress(int64_t milli_sec);//歌曲进度void volumeSliderChanged(int value);//音量改变时发生void causePlayBtnClicked();//播放按钮按下,调用void causeStopBtnClicked();//停止按钮按下,调用void causeNextBtnClicked();//下一首按钮按下,调用void causeLastBtnClicked();//上一首按钮按下,调用signals:void volumeChanged(int value);//发出音量改变信号void playBtnClicked();//发出播放信号void stopBtnClicked();//发出停止信号void nextBtnClicked();//发出下一首信号void lastBtnClicked();//发出上一首信号private:int64_t total_millisec;//当前歌曲总时间};#endif // CONTRO_PANEL_H

control_panel.cpp

#include "contro_panel.h"#include "QSlider"#include "QLabel"#include "QPushButton"#include "QHBoxLayout"#include "QVBoxLayout"#include "QGridLayout"#include "QStyle"ControlPanel::ControlPanel(QWidget *parent) : QWidget(parent){total_time = "/00:00";current_time = "00:00";this->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);stop_btn = new QPushButton();stop_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaStop));last_btn = new QPushButton();last_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaSkipBackward));play_btn = new QPushButton();play_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));next_btn = new QPushButton();next_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaSkipForward));orderplay_btn = new QPushButton();orderplay_btn->setIcon(this->style()->standardIcon(QStyle::SP_ArrowDown));volume_btn = new QPushButton();volume_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaVolume));music_progress = new QSlider();music_progress->setOrientation(Qt::Horizontal);time_label = new QLabel(current_time + total_time);time_label->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);QHBoxLayout * layout1 = new QHBoxLayout();layout1->addWidget(music_progress);layout1->addWidget(time_label);volume_slider = new QSlider();volume_slider->setOrientation(Qt::Horizontal);QHBoxLayout * layout2 = new QHBoxLayout();layout2->addStretch();//layout2->addWidget(orderplay_btn);layout2->addWidget(stop_btn);layout2->addWidget(last_btn);layout2->addWidget(play_btn);layout2->addWidget(next_btn);layout2->addWidget(volume_btn);layout2->addWidget(volume_slider);layout2->addStretch();QVBoxLayout * layout = new QVBoxLayout();layout->addLayout(layout1);layout->addLayout(layout2);this->setLayout(layout);connect(volume_slider, &QSlider::valueChanged, this, &ControlPanel::volumeSliderChanged);connect(play_btn, &QPushButton::clicked, this, &ControlPanel::causePlayBtnClicked);connect(stop_btn, &QPushButton::clicked, this, &ControlPanel::causeStopBtnClicked);connect(last_btn, &QPushButton::clicked, this, &ControlPanel::causeLastBtnClicked);connect(next_btn, &QPushButton::clicked, this, &ControlPanel::causeNextBtnClicked);}void ControlPanel::updateProgress(int64_t milli_sec){int64_t total_seconds;int seconds;int minutes;QString sec;QString min;total_seconds = static_cast<int64_t>(milli_sec / 1000);minutes = static_cast<int>(total_seconds / 60);seconds = static_cast<int>(total_seconds % 60);sec = QString::number(seconds);min = QString::number(minutes);current_time = min + ":" + sec;time_label->setText(current_time + total_time);int bar_percentage;float percentage;if(total_millisec == 0){return;} else {percentage = static_cast<float>( milli_sec )/ total_millisec;bar_percentage = static_cast<int>(percentage * 100);}music_progress->setValue(bar_percentage);}//设定当前歌曲总时长void ControlPanel::changeTotalTime(qint64 duration){total_millisec = duration;int64_t total_seconds;int seconds;int minutes;QString sec;QString min;total_seconds = static_cast<int64_t>(duration / 1000);minutes = static_cast<int>(total_seconds / 60);seconds = static_cast<int>(total_seconds % 60);sec = QString::number(seconds);min = QString::number(minutes);total_time = "/" + min + ":" + sec;time_label->setText(current_time + total_time);}void ControlPanel::causeNextBtnClicked(){emit nextBtnClicked();}void ControlPanel::causeLastBtnClicked(){emit lastBtnClicked();}void ControlPanel::volumeSliderChanged(int value){emit volumeChanged(value);}void ControlPanel::causePlayBtnClicked(){emit playBtnClicked();}void ControlPanel::causeStopBtnClicked(){emit stopBtnClicked();}ControlPanel::~ControlPanel(){}

这个模块的作用总结来说是:发出五个信号,接受两个信息。五个信号指的是播放、停止、下一首、上一首、以及音量改变。两个信息指的是当前歌曲总时长、当前歌曲已经播放时长。

播放器模块

这里要谈的是QMediaPlayer的用法,这个类可以用来播放音频、视频、网络媒体。以本地音频上的具体用法为例,如下所示:

player = new QMediaPlayer;//新建一个媒体播放器类connect(player, SIGNAL(positionChanged(qint64)), this, SLOT(positionChanged(qint64)));//当这个媒体播放器的进度改变时会发出一个信号指示当前进度,我们要写一个槽函数用来处理这个信号player->setMedia(QUrl::fromLocalFile("/Users/me/Music/coolsong.mp3"));//设置要播放的媒体player->setVolume(50);//设置音量player->play();//播放

还有更多用法以及更详细的说明,见官方帮助文档。

顶层模块

用来将各个子模块连接为一个整体

widget.h

#ifndef WIDGET_H#define WIDGET_H#include <QWidget>class QMediaPlayer;class QMediaPlaylist;class ControlPanel;class QSplitter;class MusicWord;class QMediaContent;class QLabel;class MusicTreeList;class Widget : public QWidget{Q_OBJECTpublic:Widget(QWidget *parent = 0);~Widget();enum PlayState {STOP = 1,PLAYING = 2,PAUSE = 3};public slots:void playMusic();//用来接受控制面板发出的播放信号void setMusic(QString music_name);//用来接受音乐树目录发来的歌曲信息,用来设置当前的媒体源void setVolume(int i);//用来接受控制面板发出的改变音量信号void stopPlayer();//用来接受控制面板发出的停止信号void playNext();//接受控制面板发出的下一首信号void playLast();//接受控制面板发出的上一首信号private:QMediaPlayer * music_player;QMediaPlaylist * play_list;ControlPanel * control_panel;MusicTreeList * music_tree_list;QLabel * music_title;//用来显示当前歌曲QString path;//歌曲路径QString project_path;//我的工程路径int player_state;//播放器状态};#endif // WIDGET_H

widget.cpp

#include "widget.h"#include "contro_panel.h"#include "music_word.h"#include <QMediaPlayer>#include <QPushButton>#include "QFileDialog"#include "QFileInfo"#include "QHBoxLayout"#include "QVBoxLayout"#include "QGridLayout"#include "QMediaPlaylist"#include "QSplitter"#include "QMediaContent"#include "QLabel"#include "QFont"#include "music_tree_list.h"Widget::Widget(QWidget *parent): QWidget(parent){player_state = Widget::STOP;project_path = "C:/Users/jiage/Desktop/folder/QT/music_player/music";this->setWindowIcon( QIcon(":/picture/music.png") );control_panel = new ControlPanel();music_tree_list = new MusicTreeList;music_title = new QLabel();music_title->setAlignment(Qt::AlignHCenter);music_title->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum);QFont ff;ff.setPointSize(20);music_title->setFont(ff);QSplitter * main_splitter = new QSplitter();main_splitter->addWidget(music_tree_list);main_splitter->addWidget(music_title);main_splitter->setSizes(QList<int>{200, 600});//播放器引擎对象music_player = new QMediaPlayer();music_player->setVolume(10);control_panel->volume_slider->setValue(10);play_list = new QMediaPlaylist;QVBoxLayout *layout = new QVBoxLayout();layout->addWidget(main_splitter);layout->addWidget(control_panel);this->setLayout(layout);this->resize(550, 350);connect(music_tree_list, &MusicTreeList::currentMusic, this, &Widget::setMusic);connect(control_panel, &ControlPanel::playBtnClicked, this, &Widget::playMusic);connect(control_panel, &ControlPanel::stopBtnClicked, this, &Widget::stopPlayer);connect(control_panel, &ControlPanel::nextBtnClicked, this, &Widget::playNext);connect(control_panel, &ControlPanel::lastBtnClicked, this, &Widget::playLast);connect(control_panel, &ControlPanel::volumeChanged, this, &Widget::setVolume);connect(music_player, &QMediaPlayer::durationChanged, control_panel, &ControlPanel::changeTotalTime);connect(music_player, &QMediaPlayer::positionChanged, control_panel, &ControlPanel::updateProgress);}Widget::~Widget(){}//播放音乐void Widget::playMusic(){if( player_state == Widget::STOP || player_state == Widget::PAUSE ) {music_player->play();player_state = Widget::PLAYING;control_panel->play_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPause));} else {music_player->pause();player_state = Widget::PAUSE;control_panel->play_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));}}//设定当前音乐void Widget::setMusic(QString music_name){control_panel->play_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));player_state = Widget::STOP;path = project_path + music_name;music_player->setMedia(QUrl::fromLocalFile(path));music_name.replace(QRegExp("(/(.*)/)"), "");music_name.replace(QRegExp(".mp3"), "");music_title->setText(music_name);}//设置音量void Widget::setVolume(int i){music_player->setVolume(i);}//停止播放void Widget::stopPlayer(){player_state = Widget::STOP;control_panel->play_btn->setIcon(this->style()->standardIcon(QStyle::SP_MediaPlay));music_player->stop();}//播放下一首void Widget::playNext(){//play_list->next();qDebug() << "下一首";}//播放上一首void Widget::playLast(){//play_list->previous();qDebug() << "上一首";}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。