Qt C++ 打造音乐播放器
一、写在前面
这次我使用Qt C++编写的一款音乐播放器,通过网络获得qq音乐曲库的音乐,进行播放。这个程序的名称为泠然Music_0.1,第一个版本,这个版本只实现了单曲播放。环境:VS 2017+Qt 5.12 Win10系统。
二、写在中间
1、新建Qt项目
2、整体结构
(1)Music.h
class Music : public QWidget
{
Q_OBJECT
public:
Music(QWidget *parent = Q_NULLPTR);
~Music();
void setWidget(); //窗口界面设置
void setConnection(); //信号槽连接设置
void analyseJson(); //json字符串分析
void mousePressEvent(QMouseEvent *event); //鼠标点击事件
void mouseMoveEvent(QMouseEvent *event); //鼠标移动事件
protected slots:
void searchActClicked(); //查询action事件
void startRequest(); //http请求完毕后处理函数
void setUrl(QString); //url设置
void about(); //关于
void preBtnClicked(); //前一首按钮事件
void playBtnClicked(); //播放按钮事件
void nextBtnClicked(); //下一首
void quitClicked(); //退出
void setSlider(); //进度条设置
private:
Ui::MusicClass *ui;
QPushButton *preBtn; //上一首按钮
QPushButton *nextBtn; //下一首按钮
QPushButton *pauseBtn; //播放按钮
QLineEdit *searchLEdit; //搜索按钮
QAction *searchAct; //搜索action
QSlider *slider; //进度条
QNetworkAccessManager *manager; //网络请求,响应管理
QNetworkReply *reply; //网络响应
QSystemTrayIcon *trayIcon; //托盘按钮
QMenu *trayMenu; //托盘按钮右键菜单
QAction *quitAction;
QAction *aboutAction;
QUrl url;
QString resultJson;
QIcon icon;
QMediaPlayer *player; //媒体对象
bool playState; //播放状态
QPoint offset;
};
(2)Music.cpp
①构造函数,界面的一些控件对象
Music::Music(QWidget *parent)
: QWidget(parent),ui(new Ui::MusicClass)
{
ui->setupUi(this);
this->url = "";
this->resultJson = "";
this->icon = QIcon(":/image/Music.png");
this->playState = false;
this->preBtn = new QPushButton(this);
this->nextBtn = new QPushButton(this);
this->pauseBtn = new QPushButton(this);
this->searchLEdit = new QLineEdit(this);
this->searchAct = new QAction(this);
this->slider = new QSlider(Qt::Horizontal, this);
this->manager = new QNetworkAccessManager(this);
this->trayIcon = new QSystemTrayIcon(this);
this->trayMenu = new QMenu(this);
this->quitAction = new QAction(this);
this->aboutAction = new QAction(this);
this->setFixedSize(330,90);
this->setWidget();
this->setConnection();
this->player = new QMediaPlayer(this);
}
②setWidget():用于设置界面
void Music::setWidget()
{
this->setWindowIcon(this->icon); //设置图标,任务栏中的图标
this->setWindowFlags(Qt::FramelessWindowHint); //将标题栏删去,即没有关闭,最小化按钮,也无法移动
this->preBtn->setIcon(QIcon(":/image/left-circle.png"));
this->pauseBtn->setIcon(QIcon(":/image/play-circle.png"));
this->nextBtn->setIcon(QIcon(":/image/right-circle.png"));
this->searchAct->setIcon(QIcon(":/image/search.png"));
this->preBtn->setIconSize(QSize(30, 40));
this->pauseBtn->setIconSize(QSize(30, 40));
this->nextBtn->setIconSize(QSize(30, 40));
this->preBtn->setStyleSheet("QPushButton{border:none;}");
this->pauseBtn->setStyleSheet("QPushButton{border:none;}");
this->nextBtn->setStyleSheet("QPushButton{border:none;}");
this->searchLEdit->setStyleSheet("border-radius:15px;border-width:5px");
this->slider->setStyleSheet(" \
QSlider::add-page:Horizontal\
{ \
background-color: rgb(87, 97, 106);\
height:4px;\
}\
QSlider::sub-page:Horizontal \
{\
background-color:qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(231,80,229, 255), stop:1 rgba(7,208,255, 255));\
height:4px;\
}\
QSlider::groove:Horizontal \
{\
background:transparent;\
height:6px;\
}\
QSlider::handle:Horizontal \
{\
height: 30px;\
width:8px;\
margin: -8 0px; \
}\
");
this->searchLEdit->setPlaceholderText(tr("搜索歌曲"));
this->searchLEdit->setClearButtonEnabled(true);
this->searchLEdit->setTextMargins(2, 0, 0, 0);
this->searchLEdit->setFont(QFont("宋体",14,QFont::Bold));
this->searchLEdit->setGeometry(QRect(QPoint(10, 10),QPoint( 200, 50)));
this->preBtn->setGeometry(QRect(QPoint(210, 10), QPoint(240, 50)));
this->pauseBtn->setGeometry(QRect(QPoint(250, 10), QPoint(280, 50)));
this->nextBtn->setGeometry(QRect(QPoint(290, 10), QPoint(320, 50)));
this->slider->setGeometry(QRect(QPoint(10, 60), QPoint(320, 70)));
this->searchLEdit->addAction(this->searchAct, QLineEdit::TrailingPosition);
this->aboutAction->setIcon(QIcon(":/image/info-circle.png"));
this->aboutAction->setText("关于");
this->quitAction->setIcon(QIcon(":/image/close-circle.png"));
this->quitAction->setText("退出");
this->trayIcon->setIcon(this->icon); //系统托盘图标
this->trayMenu->addAction(this->aboutAction); //右键图标显示的菜单
this->trayMenu->addSeparator();
this->trayMenu->addAction(this->quitAction);
this->trayIcon->setContextMenu(this->trayMenu);
this->preBtn->setEnabled(false);
this->nextBtn->setEnabled(false);
this->pauseBtn->setEnabled(false);
}
大概就是下面这个样子
③setConnection():设置信号槽的连接
void Music::setConnection()
{
connect(this->searchAct, &QAction::triggered, this, &Music::searchActClicked);
//当请求访问结束后,转向另一个函数。
connect(this->manager, &QNetworkAccessManager::finished, this, &Music::startRequest);
connect(this->quitAction, &QAction::triggered, this, &Music::quitClicked);
connect(this->aboutAction, &QAction::triggered, this, &Music::about);
connect(this->preBtn, &QPushButton::clicked, this, &Music::preBtnClicked);
connect(this->pauseBtn, &QPushButton::clicked, this, &Music::playBtnClicked);
connect(this->nextBtn, &QPushButton::clicked, this, &Music::nextBtnClicked);
}
④searchActClicked():这个函数是搜索action的点击事件
void Music::searchActClicked()
{
QString songName = this->searchLEdit->text();
this->setUrl(songName); //处理url
//以get方式向服务器请求访问
this->reply = this->manager->get(QNetworkRequest(this->url));
}
⑤startRequest():manager以get方式发送请求完毕时处理接收到的信息
void Music::startRequest()
{
//读取接收到的信息
this->resultJson = this->reply->readAll();
//对接收到的信息进行分析,得到我们需要的信息
this->analyseJson();
//媒体设置media
this->player->setMedia(QMediaContent(this->url));
this->pauseBtn->setEnabled(true);
//进度条,当媒体内容的进度发生改变,进度条位置也发生相应改变
connect(this->player, &QMediaPlayer::positionChanged, this, &Music::setSlider);
this->slider->setValue(0);
}
⑥setUrl():因为对前端知识不够熟练,而QQ音乐的的代码有点复杂,所以使用的是别人的爬取API,而歌曲名就嵌在请求的URL中,
void Music::setUrl(QString url)
{
this->url = QString("https://api.bzqll.com/music/tencent/search?key=579621905&s=%1&limit=100&offset=0&type=song").arg(url);
}
⑦about():
void Music::about()
{
QMessageBox::information(this, "关于", "音乐播放器\n是从QQ音乐曲库中查取并播放。\n Music version 0.1\nby 泠然", "确定");
}
⑧preBtnClicked():暂未实现
⑨nextBtnClicked():暂未实现
⑩playBtnClickde():播放控制按钮
void Music::playBtnClicked()
{
if (!this->playState)
{
this->player->play();
this->pauseBtn->setIcon(QIcon(":/image/time out.png"));
this->playState = true;
}
else
{
this->player->pause();
this->pauseBtn->setIcon(QIcon(":/image/play-circle.png"));
this->playState = false;
}
}
⑪quitClicked():关闭事件
void Music::quitClicked()
{
//QApplication的对象 qApp
qApp->quit();
}
⑫setSlider():
void Music::setSlider()
{
this->slider->setMaximum(this->player->duration());
this->slider->setMinimum(0);
this->slider->setValue(this->player->position());
if (this->player->position() == this->player->duration())
{
this->pauseBtn->setIcon(QIcon(":/image/play-circle.png"));
this->playState = false;
this->slider->setValue(0);
this->player->stop();
this->pauseBtn->setEnabled(false);
}
}
⑬analyseJson():解析json
void Music::analyseJson()
{
QByteArray jsonStr = this->resultJson.toUtf8();
QJsonDocument jsonDom = QJsonDocument::fromJson(jsonStr);
QJsonObject rootObj = jsonDom.object();
if (rootObj.contains("data"))
{
QJsonArray dataArray = rootObj.value("data").toArray();
QJsonObject firstObj = dataArray.at(0).toObject();
QString url = firstObj.value("url").toString();
this->url = url;
}
}
⑬mousePressEvent():鼠标点击事件
void Music::mousePressEvent(QMouseEvent * event)
{
if (event->button() == Qt::LeftButton)
{
this->offset = event->globalPos() - this->pos();//获得鼠标的位置与窗口的位置之间的差值
}
}
⑭mouseMoveEvent():鼠标移动事件
void Music::mouseMoveEvent(QMouseEvent * event)
{
if (event->buttons() == Qt::LeftButton)
{
QPoint temp;
temp = event->globalPos() -this->offset;
this->move(temp);
}
}
⑮直接在VS中用Qt写,输入中文时会乱码,需要在头文件中加入几行代码
#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif
三、写在最后
这个程序功能极其单一,只能搜一曲,播一曲;没有任何容错能力,没有判断曲库是否有歌,没有判断输入是否正确,没有判断网络是否连接。所以第一版非常low,后面会更新第二版。