- 最近在学Qt,想起以前做项目的时候基本上都不会写,我怕未来忘记自己做过些什么了!所以总觉得写下来好一点,用于改进自己的开发思路。
1、确定项目需求,界面设计
我喜欢上来确定项目需求,功能设计!向以前写作文一样,总觉得第一感觉是最稳的。但是这样的坏处是考虑不周,长时间停留在计划上。
需求分析:
- 显示歌词
- 暂停播放
- 上一曲,下一曲
- 显示歌曲进度
- 音量大小
大概就是模仿网易云音乐的播放界面。
因为考虑到要烧写到开发板上,开发板屏幕是800*480的,所以就这个尺寸了。
2、 开辟进程
void MainWindow::initProcess()
{
codec = QTextCodec::codecForName("GBK");
//创建播放进程
playProcess = new QProcess(this);
//关联相关的信号,进程启动成功、出错、有数据可读等
connect(playProcess,&QProcess::started,this,&MainWindow::onStarted);
connect(playProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(onError()));
connect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadD()));
connect(playProcess,SIGNAL(finished(int)),this,SLOT(onPlayProcessFinished()));
//程序名称
#ifdef Q_OS_WIN
program = "C:/MPlayer_Windows/MPlayer_core.exe";
#else
program = "mplayer";
#endif
//创建定时器
timer = new QTimer(this);
connect(timer,&QTimer::timeout,this,&MainWindow::onTimeout);
}
3、文件操作,加载歌词音乐
void MainWindow::loadMusic()
{
musicPath = "../mp3/"; //定位MP3的位置
QDir dir(musicPath); //打开目录
QStringList filters; //解析MP3
filters << "*.wma" << "*.mp3"; //*.wma ??
playList = dir.entryList(filters);//添加到列表
qDebug() << playList;
filters.clear();
filters << "*.lrc"; //歌词文件?
lrcList = dir.entryList(filters);
qDebug() << lrcList;
}
4、播放音乐和歌词
//播放音乐
void MainWindow::playMusic(QString mp3Name)
{
//将路径与歌曲名联合
QString absMp3Name = musicPath + mp3Name;
playProcess->close();
argList.clear();
argList << "-slave" << "-quiet" << absMp3Name; //在后台运行
playProcess->start(program,argList);
playProcess->write("volume 100 1\n"); //yin liang shezhi
ui->voiceslider->setValue(100);
//显示歌词
showLrc(mp3Name);
}
//显示歌词
void MainWindow::showLrc(QString mp3Name)
{
mp3Name.chop(3);
QString lrcName = mp3Name + "lrc";
qDebug() << "lrc : " << lrcName;
//迭代器
QStringList::const_iterator it;
it = qFind(lrcList,lrcName);
if(it == lrcList.end()) //没有找到对应的歌词
{
//清空列表
ui->listWidget->clear();
return ;
}
lrcTimeList.clear(); //清空时间列表
ui->listWidget->clear();
ui->listWidget->verticalScrollBar()->setSliderPosition(0);
QString absLrcName = musicPath + lrcName;
QFile file(absLrcName);
if(!file.open(QIODevice::ReadOnly))
{
qDebug() << "open lrc error" << file.errorString();
return ;
}
QTextStream in(&file);
in.setCodec("GBK");
while(!in.atEnd())
{
QString line = in.readLine();
QRegExp reg("\\[[0-9]{2,2}:[0-9]{2,2}\\.[0-9]{2,2}\\]");
bool ok = line.contains(reg);
if(ok)
{
//[01:20.31] 01 20 3,精确到百毫秒
double t = line.mid(1,2).toInt()*60 + line.mid(4,2).toInt() + line.mid(7,1).toDouble()/10;
lrcTimeList << t;
line.remove(reg);
QListWidgetItem *item = new QListWidgetItem(line);
item->setTextAlignment(Qt::AlignCenter);
ui->listWidget->addItem(item);
}
}
}
详细代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QScrollBar>
#include <QIcon>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),index(0),state(NoState),islove(false),voice(false),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setFixedSize(800,480); //设置主屏幕大小
loadMusic();
initProcess();
//listwidget 设置
ui->listWidget->verticalScrollBar()->setValue(10);
ui->listWidget->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->listWidget->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
ui->voiceslider->setVisible(false);
connect(ui->voiceslider,SIGNAL(valueChanged(int)),this,SLOT(valueChanged(int)));
}
MainWindow::~MainWindow()
{
playProcess->close();
delete ui;
}
void MainWindow::initProcess()
{
codec = QTextCodec::codecForName("GBK");
//创建播放进程
playProcess = new QProcess(this);
//关联相关的信号,进程启动成功、出错、有数据可读等
connect(playProcess,&QProcess::started,this,&MainWindow::onStarted);
connect(playProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(onError()));
connect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadD()));
connect(playProcess,SIGNAL(finished(int)),this,SLOT(onPlayProcessFinished()));
//程序名称
#ifdef Q_OS_WIN
program = "C:/MPlayer_Windows/MPlayer_core.exe";
#else
program = "mplayer";
#endif
//创建定时器
timer = new QTimer(this);
connect(timer,&QTimer::timeout,this,&MainWindow::onTimeout);
}
void MainWindow::loadMusic()
{
musicPath = "../mp3/"; //定位MP3的位置
QDir dir(musicPath); //打开目录
QStringList filters; //解析MP3
filters << "*.wma" << "*.mp3"; //*.wma ??
playList = dir.entryList(filters);//添加到列表
qDebug() << playList;
filters.clear();
filters << "*.lrc"; //歌词文件?
lrcList = dir.entryList(filters);
qDebug() << lrcList;
}
//播放音乐
void MainWindow::playMusic(QString mp3Name)
{
//将路径与歌曲名联合
QString absMp3Name = musicPath + mp3Name;
playProcess->close();
argList.clear();
argList << "-slave" << "-quiet" << absMp3Name; //在后台运行
playProcess->start(program,argList);
playProcess->write("volume 100 1\n"); //yin liang shezhi
ui->voiceslider->setValue(100);
//显示歌词
showLrc(mp3Name);
}
//显示歌词
void MainWindow::showLrc(QString mp3Name)
{
mp3Name.chop(3);
QString lrcName = mp3Name + "lrc";
qDebug() << "lrc : " << lrcName;
//迭代器
QStringList::const_iterator it;
it = qFind(lrcList,lrcName);
if(it == lrcList.end()) //没有找到对应的歌词
{
//清空列表
ui->listWidget->clear();
return ;
}
lrcTimeList.clear(); //清空时间列表
ui->listWidget->clear();
ui->listWidget->verticalScrollBar()->setSliderPosition(0);
QString absLrcName = musicPath + lrcName;
QFile file(absLrcName);
if(!file.open(QIODevice::ReadOnly))
{
qDebug() << "open lrc error" << file.errorString();
return ;
}
QTextStream in(&file);
in.setCodec("GBK");
while(!in.atEnd())
{
QString line = in.readLine();
QRegExp reg("\\[[0-9]{2,2}:[0-9]{2,2}\\.[0-9]{2,2}\\]");
bool ok = line.contains(reg);
if(ok)
{
//[01:20.31] 01 20 3,精确到百毫秒
double t = line.mid(1,2).toInt()*60 + line.mid(4,2).toInt() + line.mid(7,1).toDouble()/10;
lrcTimeList << t;
line.remove(reg);
QListWidgetItem *item = new QListWidgetItem(line);
item->setTextAlignment(Qt::AlignCenter);
ui->listWidget->addItem(item);
}
}
}
void MainWindow::on_btn_play_clicked()
{
if(playList.size() > 0)
{
if(state == NoState)
{
//qDebug() << "Nostate :" <<state ;
index = 0;
playMusic(playList.at(index));
}
else if(state == Playing)
{
//qDebug() << "playing :" << state ;
timer->stop();
state = Pause;
playProcess->write("pause\n");
ui->btn_play->setStyleSheet("border-image: url(:/play.png);");
ui->btn_song->setStyleSheet("border-image: url(:/playmain.png);");
}
else if(state == Pause)
{
qDebug() << "pause :" <<state ;
state = Playing;
playProcess->write("pause\n");
//ui->btn_play->setText(tr("暂停"));
ui->btn_play->setStyleSheet("border-image: url(:/stop.png);");
ui->btn_song->setStyleSheet("border-image: url(:/stopmain.png);");
timer->start();
}
}
}
//启动进程成功
void MainWindow::onStarted()
{
qDebug("playing~~");
state = Playing;
//ui->btn_play->setText(tr("暂停"));
ui->btn_play->setStyleSheet("border-image: url(:/stop.png);");
ui->btn_song->setStyleSheet("border-image: url(:/stopmain.png);");
playProcess->write("get_time_length\n");
timer->start(40);
}
//错误处理
void MainWindow::onError()
{
qDebug() << "error : " << playProcess->errorString();
}
void MainWindow::onReadD()
{
while(playProcess->bytesAvailable())
{
QByteArray arr = playProcess->readLine();
QString str = codec->toUnicode(arr);
if(str.contains("ANS_LENGTH"))
{//获取时间总长度
qDebug() << "::"<<str;
str.remove("\n");
str.remove("\r");
str.remove("ANS_LENGTH=");
qDebug() << "str = " << str;
int t = str.toDouble();
int m = t/60;
int s = t%60;//Because % is only defined for integer types.
tlength = m * 60 + s;
//qDebug() << "tlength:" << tlength;
QString timeLength;
timeLength.sprintf("%02d:%02d",m,s);
ui->label_time_length->setText(timeLength);
}
if(str.contains("ANS_TIME_POSITION"))//
{//获取当前时间
//qDebug() << "::"<<str;
str.remove("\n");
str.remove("\r");
double t = QString(str.split("=").at(1)).toDouble();
int index = lrcTimeList.indexOf(t);
if(index != -1)
{//根据播放时间,设置当前显示行
//ui->listWidget->setCurrentRow(index);
//设置正在播放的歌词字体变大、颜色为红色
ui->listWidget->item(index)->setFont(QFont(tr("微软雅黑"),12));
ui->listWidget->item(index)->setTextColor(Qt::white);
if(index > 1)
{//上一行改的字体与颜色还原
ui->listWidget->item(index-1)->setFont(QFont(tr("微软雅黑"),10));
ui->listWidget->item(index-1)->setTextColor(Qt::black);
}
if(index >5)
{//播放到第5行时,移动滚动条位置,使用当前显示的歌词居中显示
ui->listWidget->verticalScrollBar()->setSliderPosition(index-5);
}
}
//显示当前时间
int m = t/60;
int s = (int)t%60;
QString timePos;
timePos.sprintf("%02d:%02d",m,s);
ui->label_time_now->setText(timePos);
//qDebug() << "now: " << (m * 60 + s) << "all:" <<tlength;
int now = (m * 60 + s);
double slider = now * 100 / tlength;
//qDebug() << slider;
ui->timeSlider->setValue(slider);
}
}
}
//定时器超时
void MainWindow::onTimeout()
{
playProcess->write("get_time_pos\n");
}
void MainWindow::valueChanged(int volumes)
{
playProcess->write("volume %d 1\n",volumes);
}
//播放进程结束
void MainWindow::onPlayProcessFinished()
{
qDebug() << "process finished";
timer->stop();
state = NoState;
//ui->btn_play->setText(tr("播放"));
ui->btn_play->setStyleSheet("border-image: url(:/start.png);");
}
//下一首
void MainWindow::on_btn_next_clicked()
{
if(index < playList.size()-1)
{
index++;
// QString mp3Name = musicPath + playList.at(index);
playMusic(playList.at(index));
}
else
{
return;
}
}
//上一首
void MainWindow::on_btn_last_clicked()
{
if(index > 0)
{
index--;
// QString mp3Name = musicPath + playList.at(index);
playMusic(playList.at(index));
}
else
{
return;
}
}
void MainWindow::on_btn_love_clicked()
{
if(islove == false)
{
islove = true;
ui->btn_love->setStyleSheet("border-image: url(:/islove.png);");
}
else
{
islove = false;
ui->btn_love->setStyleSheet("border-image: url(:/nolove.png);");
}
}
void MainWindow::on_btn_song_clicked()
{
on_btn_play_clicked();
}
void MainWindow::on_btn_voice_clicked()
{
if(voice == false)
{
voice = true;
ui->voiceslider->setVisible(true);
}
else
{
voice = false;
ui->voiceslider->setVisible(false);
}
}
最后是效果