在用Qt写一个简单的音乐播放器(一):使用QMediaPlayer播放音乐中,我们已经知道如何去使用QMediaPlayer播放音乐。
在用Qt写一个简单的音乐播放器(二):增加界面(开始和暂停音乐)中,我们增加了播放音乐/暂停音乐的按钮。
在用Qt写一个简单的音乐播放器(三):增加界面(播放跳转与音量控制)中,我们加入了播放控制和音量控制。
在用Qt写一个简单的音乐播放器(四):歌曲浏览、上一曲、下一曲中,我们增加了歌曲选择的功能。
在用Qt写一个简单的音乐播放器(五):歌曲播放时间显示中,我们为歌曲播放增加播放时间显示。
那么第六篇文章来谈一谈如何显示歌词:
如上图所示,歌词文件的内容形式为一行一句,所以我们可以将歌词文件逐行读入,代码如下。
mainwindow.cpp中做如下修改
void MainWindow::on_lwMusicList_itemDoubleClicked(QListWidgetItem *item)
{
m_PlayRow = ui->lwMusicList->row(item);
m_mediaPlayer.stop();
m_mediaPlayer.setMedia(QUrl::fromLocalFile(m_playPath+"/"+item->text()));
m_mediaPlayer.play();
QString name = item->text().left(item->text().lastIndexOf("."));
if(!lyrics.readLyricsFile(m_playPath+"/"+name+".lrc")){
ui->lblLyrics1->setText("未检测到歌词文件");
ui->lblLyrics2->setText("请检查歌词文件是否存在");
}
lyricsID = 0;
ui->hSliderPlayProgress->setValue(m_mediaPlayer.position());
ui->btnPlay->setText("Pause");
connect(timer, SIGNAL(timeout()), this, SLOT(setSliderValue()));
connect(&m_mediaPlayer,SIGNAL(durationChanged(qint64)),this,SLOT(getduration()));
connect(&m_mediaPlayer,SIGNAL(positionChanged(qint64)),this,SLOT(setPlayTime()));
}
新建一个lyrics类文件,加入以下代码:
bool Lyrics::readLyricsFile(QString lyricsPath)
{
QFile file(lyricsPath);
file.open(QIODevice::ReadOnly | QIODevice::Text);
QString line="";
while((line=file.readLine())>0){
qDebug()<<line;
analysisLyricsFile(line);//解析歌词文件内容
}
return true;
}
歌词读取一行,我们就对这个歌词进行解析。我这里将歌词分为了两部分:时间和内容。用正则表达式匹配后,将时间计算为毫秒存入listLyricsTime,将内容存入listLyricsText。
bool Lyrics::analysisLyricsFile(QString line)
{
if(line == NULL || line.isEmpty()){
qDebug()<<"thie line is empty!";
return false;
}
QRegularExpression regularExpression("\\[(\\d+)?:(\\d+)?(\\.\\d+)?\\](.*)?");
int index = 0;
QRegularExpressionMatch match;
match = regularExpression.match(line, index);
if(match.hasMatch()) {
int totalTime;
totalTime = match.captured(1).toInt() * 60000 + match.captured(2).toInt() * 1000; /* 计算该时间点毫秒数 */
QString currentText =QString::fromStdString(match.captured(4).toStdString()); /* 获取歌词文本*/
listLyricsText.push_back(currentText);
listLyricsTime.push_back(totalTime);
return true;
}
return false;
}
如图所示:拖两个label,一个用来显示播放当前歌词(设置为左对齐),一个用来显示下一句歌词(设置为右对齐)。
在播放时间改变的时候,判断当前音乐的播放时间,是否大于歌词时间,若大于,则显示歌词。代码如下:
void MainWindow::setPlayTime()
{
if(!lyrics.getListLyricsTime().empty()&&m_mediaPlayer.position()>=lyrics.getListLyricsTime().at(lyricsID)){
ui->lblLyrics1->setText(lyrics.getListLyricsText().at(lyricsID));
ui->lblLyrics2->setText(lyrics.getListLyricsText().at(lyricsID+1));
lyricsID++;
}
ui->lblPlayTime->setText(settime(m_mediaPlayer.position()));
}
当然这个完整也只是相对完整,不过这个基本已经很全了。
#include "lyrics.h"
QList<QString> Lyrics::getListLyricsText() const
{
return listLyricsText;
}
QList<int> Lyrics::getListLyricsTime() const
{
return listLyricsTime;
}
Lyrics::Lyrics(QString lyricsPath)
{
this->lyricsPath = lyricsPath;
}
Lyrics::Lyrics()
{
}
bool Lyrics::readLyricsFile(QString lyricsPath)
{
QFile file(lyricsPath);
if(!file.open(QIODevice::ReadOnly | QIODevice::Text)){
listLyricsText.clear();
listLyricsTime.clear();
return false;
}
QString line="";
while((line=file.readLine())>0){
qDebug()<<line;
analysisLyricsFile(line);
}
return true;
}
bool Lyrics::analysisLyricsFile(QString line)
{
if(line == NULL || line.isEmpty()){
qDebug()<<"thie line is empty!";
return false;
}
QRegularExpression regularExpression("\\[(\\d+)?:(\\d+)?(\\.\\d+)?\\](.*)?");
int index = 0;
QRegularExpressionMatch match;
match = regularExpression.match(line, index);
if(match.hasMatch()) {
int totalTime;
totalTime = match.captured(1).toInt() * 60000 + match.captured(2).toInt() * 1000; /* 计算该时间点毫秒数 */
QString currentText =QString::fromStdString(match.captured(4).toStdString()); /* 获取歌词文本*/
qDebug()<<totalTime;
qDebug()<<currentText;
listLyricsText.push_back(currentText);
listLyricsTime.push_back(totalTime);
return true;
}
return false;
}
#ifndef LYRICS_H
#define LYRICS_H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
class Lyrics
{
private:
QString lyricsPath;
QList<QString> listLyricsText;
QList<int> listLyricsTime;
public:
Lyrics(QString lyricsPath);
Lyrics();
bool readLyricsFile(QString lyricsPath);
bool analysisLyricsFile(QString line);
QList<QString> getListLyricsText() const;
QList<int> getListLyricsTime() const;
};
#endif // LYRICS_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
timer = new QTimer();
timer->setInterval(2000);
timer->start();
ui->vSliderVolume->setVisible(false);
QString fileName = "D:/music";
QDir dir(fileName);
QStringList nameFilters;
nameFilters << "*.mp3";
QStringList files = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name);
ui->lwMusicList->addItems(files);
m_playPath = fileName;
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_btnPlay_clicked()
{
if(QMediaPlayer:: PlayingState == m_mediaPlayer.state()){
m_mediaPlayer.pause();
ui->btnPlay->setText("Play");
}
else{
m_mediaPlayer.play();
ui->btnPlay->setText("Pause");
}
}
void MainWindow::on_hSliderPlayProgress_sliderMoved(int position)
{
m_mediaPlayer.setPosition(m_mediaPlayer.duration()*position/100);
}
void MainWindow::setSliderValue()
{
ui->hSliderPlayProgress->setValue(m_mediaPlayer.position()*100/m_mediaPlayer.duration());
if(m_mediaPlayer.position()>=m_mediaPlayer.duration()){
on_btnNextMusic_clicked();
}
}
void MainWindow::on_vSliderVolume_sliderMoved(int position)
{
m_mediaPlayer.setVolume(position);
}
void MainWindow::on_lwMusicList_itemDoubleClicked(QListWidgetItem *item)
{
m_PlayRow = ui->lwMusicList->row(item);
m_mediaPlayer.stop();
m_mediaPlayer.setMedia(QUrl::fromLocalFile(m_playPath+"/"+item->text()));
m_mediaPlayer.play();
QString name = item->text().left(item->text().lastIndexOf("."));
if(!lyrics.readLyricsFile(m_playPath+"/"+name+".lrc")){
ui->lblLyrics1->setText("未检测到歌词文件");
ui->lblLyrics2->setText("请检查歌词文件是否存在");
}
lyricsID = 0;
ui->hSliderPlayProgress->setValue(m_mediaPlayer.position());
ui->btnPlay->setText("Pause");
connect(timer, SIGNAL(timeout()), this, SLOT(setSliderValue()));
connect(&m_mediaPlayer,SIGNAL(durationChanged(qint64)),this,SLOT(getduration()));
connect(&m_mediaPlayer,SIGNAL(positionChanged(qint64)),this,SLOT(setPlayTime()));
}
void MainWindow::on_btnAddMusic_clicked()
{
QString fileName = QFileDialog::getExistingDirectory(NULL,"Select Music Dir",".",NULL);
QDir dir(fileName);
QStringList nameFilters;
nameFilters << "*.mp3";
QStringList files = dir.entryList(nameFilters, QDir::Files|QDir::Readable, QDir::Name);
ui->lwMusicList->addItems(files);
m_playPath = fileName;
}
void MainWindow::on_btnPreMusic_clicked()
{
if(m_PlayRow == 0){
m_PlayRow = ui->lwMusicList->count() - 1;
}
else{
m_PlayRow--;
}
QListWidgetItem *item = ui->lwMusicList->item(m_PlayRow);
item->setSelected(true);
m_mediaPlayer.stop();
m_mediaPlayer.setMedia(QUrl::fromLocalFile(m_playPath+"/"+item->text()));
m_mediaPlayer.play();
}
void MainWindow::on_btnNextMusic_clicked()
{
if(m_PlayRow + 1 == ui->lwMusicList->count()){
m_PlayRow = 0;
}
else{
m_PlayRow++;
}
QListWidgetItem *item = ui->lwMusicList->item(m_PlayRow);
item->setSelected(true);
m_mediaPlayer.stop();
m_mediaPlayer.setMedia(QUrl::fromLocalFile(m_playPath+"/"+item->text()));
m_mediaPlayer.play();
}
void MainWindow::on_btnVolume_clicked()
{
if(ui->vSliderVolume->isVisible()){
ui->vSliderVolume->setVisible(false);
}else{
ui->vSliderVolume->setVisible(true);
}
}
void MainWindow::on_vSliderVolume_sliderReleased()
{
ui->vSliderVolume->setVisible(false);
}
QString MainWindow::settime(int time)
{
int h,m,s;
time /= 1000; //获得的时间是以毫秒为单位的
h = time/3600;
m = (time-h*3600)/60;
s = time-h*3600-m*60;
return QString("%1:%2:%3").arg(h).arg(m).arg(s);
}
void MainWindow::getduration()
{
playtime = m_mediaPlayer.duration();
ui->lblMusicTime->setText(settime(playtime));
}
void MainWindow::setPlayTime()
{
if(!lyrics.getListLyricsTime().empty()&&m_mediaPlayer.position()>=lyrics.getListLyricsTime().at(lyricsID)&&lyricsID<lyrics.getListLyricsTime().size()-1){
ui->lblLyrics1->setText(lyrics.getListLyricsText().at(lyricsID));
ui->lblLyrics2->setText(lyrics.getListLyricsText().at(lyricsID+1));
lyricsID++;
}
ui->lblPlayTime->setText(settime(m_mediaPlayer.position()));
}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include // 包含头文件
#include
#include
#include
#include
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QString settime(int time);
private slots:
void on_btnPlay_clicked();
void on_hSliderPlayProgress_sliderMoved(int position);
void setSliderValue();
void on_vSliderVolume_sliderMoved(int position);
void on_lwMusicList_itemDoubleClicked(QListWidgetItem *item);
void on_btnAddMusic_clicked();
void on_btnPreMusic_clicked();
void on_btnNextMusic_clicked();
void on_btnVolume_clicked();
void on_vSliderVolume_sliderReleased();
void getduration();
void setPlayTime();
private:
Ui::MainWindow *ui;
QMediaPlayer m_mediaPlayer; // 实例化对象
QTimer *timer; //定时器
QString m_playPath;
Lyrics lyrics;
int m_PlayRow;
int playtime;
int lyricsID = 0;
};
#endif // MAINWINDOW_H
从无到有,从最开始的播放音乐、开始、暂停、播放时间、跳转播放、音量控制、选择歌曲,到今天的歌词显示,一个简单的本地音乐播放器也终于写完了。当然它很丑,但是至少也是基本的功能也都有不是,剩下的界面美化啊,网络播放啊,等等功能吧,以后慢慢优化吧,当然现在这个代码也是有一定问题的,bug不少,代码结构也不好,以后功能越来越多的时候,肯定是要重构的。
用Qt写一个简单的音乐播放器(七):界面美化(QSS样式表)