功能介绍:
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();
}
(转载请注明作者和出处, 未经允许请勿用于商业用途)