功能介绍:
MP3播放器
构思过程:满足基本的播放要求(播放/暂停,快进,快退),带有歌词显示,标签显示,带曲目列表,支持中文
用到的工具(平台:Windows XP SP3):
编程语言:C++
图标制作:Photo shop
音频文件标签库:mediaInfo(第三方库)
标签编码转换:sqlite3数据库及sqlite3 C++库(提前已经将对应的unicode和gbk编码用C++录入sqlite3数据库,过程如果遇到需要,则直接查表调用即可)
文件目录:
程序运行界面:
初始状态
添加多个文件状态
列表横向摆放
主要代码部分
/* *功能: 音频播放器 *作者: KAKASI (gongsunyongwu@163.com) *时间: 2014-6-1 *版本: V1.0 * */ #include "musicPlayer.h" #include <QHBoxLayout> #include <QVBoxLayout> #include <QGridLayout> #include <QPixmap> #include <QBitmap> #include <QPainter> #include <QIcon> #include <QFile> #include <QTextStream> #include <QPushButton> #include <QMediaMetaData> #include <QDebug> #include <QLibrary> #include <stdio.h> #include <QFileInfo> #include <QFileDialog> #include <QLocale> #include <iostream> #include <QByteArray> #include <iostream> #include <QByteArray> #include <string.h> #include <stdlib.h> #include <locale.h> #include <bitset> #include <iomanip> #include <QTextCodec> #include "QMediaInfo.h" using namespace std; #define cout qDebug() MusicPlayer::MusicPlayer(QWidget *parent) :QWidget(parent) { //some information init this->setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint); isMouseDown = false; QPushButton *listBtn = new QPushButton("L"); listBtn->setMaximumSize(20,20); connect(listBtn, SIGNAL(clicked()), SLOT(showList())); listBtn->setStyleSheet("background:gray"); QPushButton *loadBtn = new QPushButton("O"); loadBtn->setMaximumSize(20,20); connect(loadBtn, SIGNAL(clicked()), SLOT(loadMusics())); loadBtn->setStyleSheet("background:gray"); QPushButton *minBtn = new QPushButton("-"); minBtn->setMaximumSize(20,20); connect(minBtn, SIGNAL(clicked()), SLOT(setMin())); minBtn->setStyleSheet("background:gray"); QPushButton *exitBtn = new QPushButton("X"); exitBtn->setMaximumSize(30,20); connect(exitBtn, SIGNAL(clicked()),SLOT(close())); exitBtn->setStyleSheet("background:gray; text-align:top"); QHBoxLayout *titleLayout = new QHBoxLayout; titleLayout->addStretch(); titleLayout->addWidget(listBtn,0,Qt::AlignTop); titleLayout->addWidget(loadBtn,0,Qt::AlignTop); titleLayout->addWidget(minBtn,0,Qt::AlignTop); titleLayout->addWidget(exitBtn,0,Qt::AlignTop); titleLayout->setSpacing(0); titleLayout->setContentsMargins(0, 0, 0, 0); //layout musicNameLabel = new MyLabel(); musicNameLabel->setMinimumWidth(200); musicNameLabel->setText("Take Me Away"); musicNameLabel->setStyleSheet("font-size:23px; font-family: 隶书; color:white"); authorLabel = new MyLabel(); authorLabel->setText("Avril"); authorLabel->setStyleSheet("font-size:14px; font-family:隶书; color:white"); timeLabel = new MyLabel(); totalTime = 302; timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(0)).arg(getTimeStr(totalTime))); timeLabel->setStyleSheet("font-size:14px; font-family:隶书;color:white"); volLabel = new MyLabel; volLabel->setText(tr("V:%1").arg("30%")); volLabel->setStyleSheet("font-size:14px; font-family:隶书; color:white"); QHBoxLayout *timeAndVolLabel = new QHBoxLayout; timeAndVolLabel->addWidget(volLabel); timeAndVolLabel->addStretch(); timeAndVolLabel->addWidget(timeLabel); prevLabel = new MyLabel; playOrPauseLabel = new MyLabel; nextLabel = new MyLabel; connect(playOrPauseLabel, SIGNAL(clicked()), SLOT(playOrPause())); connect(nextLabel, SIGNAL(clicked()), SLOT(next())); connect(prevLabel, SIGNAL(clicked()), SLOT(prev())); QPixmap img1("images/prev3.png"); QPixmap img2("images/play.png"); QPixmap img3("images/next3.png"); prevLabel->setPixmap(img1.scaled(40,40)); playOrPauseLabel->setPixmap(img2.scaled(60,60)); nextLabel->setPixmap(img3.scaled(40,40)); prevLabel->resize(40,40); playOrPauseLabel->resize(60,60); nextLabel->resize(40,40); prevLabel->setStyleSheet("border-style:flat;"); playOrPauseLabel->setStyleSheet("border-style:flat"); nextLabel->setStyleSheet("border-style:flat"); QString smallStyleStr = "width:40px; height:40px; "; QString bigStyleStr = "width:60px; height:60px; "; prevLabel->setStyleSheet(smallStyleStr); playOrPauseLabel->setStyleSheet(bigStyleStr); nextLabel->setStyleSheet(smallStyleStr); picLabel = new MyLabel(); picLabel->resize(85,85); picLabel->setStyleSheet("margin-left:6px;margin-right:10px;"); QPixmap pic("images/logo.png"); picLabel->setPixmap(pic); QHBoxLayout *picLayout = new QHBoxLayout; picLayout->addWidget(picLabel); space = new MyLabel; space->setText("<hr>"); currentLRC = new MyLabel("<center> </center>"); currentLRC->setStyleSheet("font-size:25px; font-family:隶书;color:DeepSkyBlue;"); nextLRC = new MyLabel("<center> </center>"); nextLRC->setStyleSheet("font-size:15px; font-family:隶书; color:LightGrey;"); progressSlider = new QSlider(Qt::Horizontal); progressSlider->setRange(0,totalTime); connect(progressSlider, SIGNAL(sliderMoved(int)), SLOT(setPosition(int))); connect(progressSlider, SIGNAL(sliderReleased()), SLOT(setPosition())); volSlider = new QSlider(Qt::Horizontal); volSlider->setRange(0,100); volSlider->setValue(30); connect(volSlider, SIGNAL(valueChanged(int)), SLOT(changeVol(int))); QFile file("qss/style1.qss"); file.open(QFile::ReadOnly); volSlider->setStyleSheet(file.readAll()); file.close(); file.setFileName("qss/style2.qss"); file.open(QFile::ReadOnly); progressSlider->setStyleSheet(file.readAll()); progressSlider->setMinimumWidth(240); QHBoxLayout *slider = new QHBoxLayout; slider->addWidget(volSlider); slider->addStretch(); slider->addWidget(progressSlider); QVBoxLayout *midLayout = new QVBoxLayout(); midLayout->addWidget(musicNameLabel); midLayout->addWidget(authorLabel); midLayout->addLayout(timeAndVolLabel); QHBoxLayout *operationLayout = new QHBoxLayout(); operationLayout->addWidget(prevLabel, 0,Qt::AlignRight); operationLayout->addWidget(playOrPauseLabel, 0, Qt::AlignRight); operationLayout->addWidget(nextLabel, 0, Qt::AlignRight); QHBoxLayout *topLayout = new QHBoxLayout; topLayout->addLayout(midLayout); topLayout->addLayout(operationLayout); QVBoxLayout *rightLayout = new QVBoxLayout; rightLayout->addLayout(topLayout); rightLayout->addLayout(slider); QVBoxLayout *lrcLayout = new QVBoxLayout; lrcLayout->addWidget(currentLRC); lrcLayout->addWidget(nextLRC); QHBoxLayout *mainLayout1 = new QHBoxLayout(); mainLayout1->addLayout(picLayout); mainLayout1->addLayout(rightLayout); QVBoxLayout *mainLayout2 = new QVBoxLayout(); mainLayout2->addLayout(titleLayout); mainLayout2->addLayout(mainLayout1); mainLayout2->addWidget(space); mainLayout2->addLayout(lrcLayout); mainLayout2->setSpacing(0); mainLayout2->setContentsMargins(5,0,15,15); this->setLayout(mainLayout2); this->resize(this->sizeHint()); //important for setRounded(bool) setAttribute(Qt::WA_TranslucentBackground, true); setRounded(true); isPlaying = false; listUi = 0; list = new QStringList; playerList = new QMediaPlaylist; playerList->setCurrentIndex(0); playerList->setPlaybackMode(QMediaPlaylist::Loop); player = new QMediaPlayer; player->setPlaylist(playerList); connect(player,SIGNAL(positionChanged(qint64)), SLOT(positionChange(qint64))); connect(player,SIGNAL(durationChanged(qint64)), SLOT(durationChange(qint64))); volSlider->setValue(player->volume()); createActions(); lrc = new QMap<int,QString>; updateInfo(); } void MusicPlayer::closeEvent(QCloseEvent *event) { if (listUi != 0) listUi->close(); event->accept(); } //显示曲目列表 void MusicPlayer::showList() { if (listUi == 0) { listUi = new MediaList(this->sizeHint(), this->pos(), this); listUi->show(); return; } if (listUi->isHidden()) { listUi->show(); } else { listUi->hide(); } } //打开音频文件 void MusicPlayer::loadMusics() { QStringList files = QFileDialog::getOpenFileNames( this, "Select one or more files to open", "/home", "musics (*.mp3 *.wma *.wav)"); int begin = list->length(); if (!files.isEmpty()) { QString str; foreach (str, files) { list->append(str); playerList->addMedia(QUrl::fromLocalFile(list->last())); } playerList->setCurrentIndex(begin); updateInfo(); if (listUi == 0) { listUi = new MediaList(this->sizeHint(), this->pos(), this); } if (listUi != 0) { listUi->addFiles(files); } } //歌词初始化 initLrc(); player->play(); QPixmap img(("images/pause.png")); playOrPauseLabel->setPixmap(img.scaled(60,60)); } //任意区域右键菜单 void MusicPlayer::contextMenuEvent(QContextMenuEvent *event) { menu->clear(); menu->addAction(openAction); menu->addAction(exitAction); menu->exec(QCursor::pos()); event->accept(); } // void MusicPlayer::createActions() { menu = new QMenu(this); openAction = new QAction("open",this); exitAction = new QAction("exit",this); } //更新界面信息 void MusicPlayer::updateInfo() { QString title; QString author; QFileInfo f; if (!list->empty()) { QString fileName = list->at(playerList->currentIndex()); info = new QMediaInfo(fileName); f.setFile(fileName); if (f.suffix().toUpper() == "MP3") { title = info->getInfo("Title",true); author = info->getInfo("Performer",true); } else { title = info->getInfo("Title"); author = info->getInfo("Performer"); } title = f.baseName(); //cout << title << author; delete info; } title.truncate(8); if (title.length() > 8) title += ".."; if (title.isEmpty()) title = "Title:Unknown"; if (author.isEmpty()) author = "Author:Unknown"; musicNameLabel->setText(title); authorLabel->setText(author); curLrc = ""; nextLrcStr = ""; currentLRC->setText("<center>" + curLrc +"</center>"); nextLRC->setText("<center>" + nextLrcStr +"</center>"); //歌词初始化 initLrc(); } //下一首 void MusicPlayer::next() { playerList->next(); //qDebug()<<playerList->currentIndex(); updateInfo(); //歌词初始化 initLrc(); } //上一首 void MusicPlayer::prev() { playerList->previous(); updateInfo(); //歌词初始化 initLrc(); } //时间更新 void MusicPlayer::durationChange(qint64 duration) { totalTime = duration; progressSlider->setRange(0, duration); timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(0)).arg(getTimeStr(totalTime))); } //进度更新 void MusicPlayer::positionChange(qint64 pos) { if (!progressSlider->isSliderDown()) progressSlider->setValue(pos); timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(pos)).arg(getTimeStr(totalTime))); //更新歌词显示getTimeStr(pos) if (lrc->empty()) return; int key = pos / 1000; QMap<int, QString>::iterator it; if (lrc->contains(key)) { curLrc = lrc->value(key); it = lrc->find(key); if (it++ != lrc->end()) { nextLrcStr = it.value(); } } curLrc = curLrc.trimmed(); curLrc.truncate(15); if (curLrc.length() > 15) curLrc += "..."; nextLrcStr = nextLrcStr.trimmed(); nextLrcStr.truncate(15); if(nextLrcStr.length() > 15) nextLrcStr += "..."; currentLRC->setText("<center>" + curLrc +"</center>"); nextLRC->setText("<center>" + nextLrcStr +"</center>"); //cout << pos << curLrc; } //初始化歌词 void MusicPlayer::initLrc() { if (lrc != 0) lrc->clear(); if (list == 0) return; curLrc = ""; nextLrcStr = ""; //思路,用一个map存储10-》string的格式,然后时间到后载入,等待下一个时间 if (list->isEmpty()) return ; if (playerList == 0) return; QString fileNames = list->at(playerList->currentIndex()); QString lrcNames = fileNames; int n = lrcNames.lastIndexOf('.'); lrcNames.replace(n,lrcNames.length() - n,".lrc"); QFile file(lrcNames); QString line; if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { QTextStream stream(&file); while(!stream.atEnd()) { line = stream.readLine(); int num = line.count('['); int last = line.lastIndexOf(']'); QString str = line.right(line.length() - last -1); int begin = 0; while(num-- >0) { QString strs = line.mid(begin,10); begin += 10; strs.replace("[",""); strs.replace("]",""); int s = getSeconds(strs); if (s > 0) { lrc->insert(s,str.trimmed()); //cout << s << "=" << lrc->value(s); } } } } } void MusicPlayer::setPosition(int pos) { currentPos = pos; } void MusicPlayer::setPosition() { player->setPosition(currentPos); } //play or pause void MusicPlayer::playOrPause() { QPixmap img(("images/play.png")); if (!isPlaying) { isPlaying = true; player->play(); img.load("images/pause.png"); } else { isPlaying = false; player->pause(); img.load("images/play.png"); } playOrPauseLabel->setPixmap(img.scaled(60,60)); } //时间字符串00:00:00得到毫秒/秒,依赖操作系统 qint32 MusicPlayer::getSeconds(QString &timeStr) { QStringList strs = timeStr.split(":"); QString s; if (strs.size() > 0) { int m = strs.at(0).toDouble(); int s = strs.at(1).toDouble(); //cout << "m" << m; //cout << "s" << s; return m * 60 + s; } return 0; } //从时,分,秒获取总数秒 qint32 MusicPlayer::getSeconds(qint32 seconds_, qint32 minutes_, qint32 hours_) { return seconds_ + minutes_ * 60 + hours_ * 3600; } //从duuation获取字符串 QString MusicPlayer::getTimeStr(qint32 seconds_) { seconds_ /= 1000; qint32 minutes = seconds_ % 3600 / 60; qint32 seconds = seconds_ % 3600 % 60; minutes = minutes > 99 ? 99 : minutes + 100; seconds = seconds + 100; return QString::number(minutes).right(2).append(":").append(QString::number(seconds).right(2)); } //改变时间提示 //void MusicPlayer::changeTime(qint64 time) //{ // timeLabel->setText(tr("T: <span style='color:Coral'>%1</span> / %2").arg(getTimeStr(time/1000)).arg(getTimeStr(totalTime))); //} //最小 void MusicPlayer::setMin() { if (!this->isMinimized()) { this->showMinimized(); } } //改变音量提示 void MusicPlayer::changeVol(int vol) { volLabel->setText(tr("V:%1%").arg(QString::number(vol))); player->setVolume(vol); } //窗体透明程度 void MusicPlayer::paintEvent(QPaintEvent *event) { QPainter painter(this); painter.fillRect(this->rect(), QColor(100, 100, 100, 255)); //QColor最后一个参数80代表背景的透明度 } //圆角窗体 void MusicPlayer::setRounded(bool b) { if (!bmp) { delete bmp; bmp = 0L; } if (!p) { delete p; p = 0L; } bmp = new QBitmap(this->size()); bmp->fill(); //fills the pixmap with white (default value) color p = new QPainter(bmp); p->setPen(Qt::NoPen); p->setBrush(Qt::black); if (b) p->drawRoundedRect(bmp->rect(),15,15); else p->drawRoundedRect(bmp->rect(),0,0); setMask(*bmp);//设置窗体遮罩 } //移动窗体相关 void MusicPlayer::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { isMouseDown = true; oldLocation = event->globalPos() - this->pos(); } event->ignore(); } //移动窗体相关 void MusicPlayer::mouseMoveEvent(QMouseEvent *event) { if (isMouseDown) { this->move(event->globalPos() - oldLocation); if (listUi != 0) { listUi->moves(this->sizeHint(), this->pos()); } } event->ignore(); } //移动窗体相关 void MusicPlayer::mouseReleaseEvent(QMouseEvent *event) { isMouseDown = false; event->ignore(); }
原文:http://blog.csdn.net/tempofwyq/article/details/37335457