STM32MP157開發(fā)板Linux+Qt項(xiàng)目實(shí)戰(zhàn):音樂播放器
stm32mp157開發(fā)板FS-MP1A是華清遠(yuǎn)見自主研發(fā)的一款高品質(zhì)、高性價(jià)比的Linux+單片機(jī)二合一的嵌入式教學(xué)級(jí)開發(fā)板。開發(fā)板搭載ST的STM32MP157高性能微處理器,集成2個(gè)Cortex-A7核和1個(gè)Cortex-M4 核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實(shí)時(shí)操作系統(tǒng)。開發(fā)板搭配仿真器、顯示屏、攝像頭、資源擴(kuò)展板等豐富的擴(kuò)展模塊,可拓展物聯(lián)網(wǎng)、人工智能等相關(guān)技術(shù)學(xué)習(xí),還可以拓展豐富的項(xiàng)目實(shí)戰(zhàn),非常貼合企業(yè)當(dāng)下開發(fā)需求,是一款嵌入式Linux入門進(jìn)階必備開發(fā)板!
?
可學(xué)習(xí)技術(shù):嵌入式Linux應(yīng)用/系統(tǒng)/驅(qū)動(dòng)開發(fā)、ARM裸機(jī)開發(fā)、Qt界面編程、STM32單片機(jī)、FreeRTOS、人工智能機(jī)器視覺等。其中ARM Cortex-A7裸機(jī)開發(fā)課程是華清遠(yuǎn)見獨(dú)有特色課程,可關(guān)注:https://www.bilibili.com/video/BV1Xe4y1i7vm/,持續(xù)更新中。

可實(shí)戰(zhàn)項(xiàng)目:14個(gè)Linux+Qt綜合項(xiàng)目案例,8個(gè)MP1A物聯(lián)網(wǎng)拓展項(xiàng)目
關(guān)注公眾號(hào)“華清遠(yuǎn)見V智能有料”,回復(fù)“mp157項(xiàng)目”,索取項(xiàng)目配套文檔及源碼。
1、Linux+Qt綜合項(xiàng)目案例:華清遠(yuǎn)見stm32mp157開發(fā)板優(yōu)勢(shì)特色部分,包括音樂播放器、智慧家庭、智能工業(yè)電表、智能出行助手、智能貓眼、環(huán)境監(jiān)測(cè)、智能安防、智能語音識(shí)別等10余個(gè)項(xiàng)目案例,涉及家居、醫(yī)療、農(nóng)業(yè)多種應(yīng)用方向,在案例中使用了多種物聯(lián)網(wǎng)和嵌入式技術(shù),包括OT開發(fā)、linux應(yīng)用開發(fā)、linux驅(qū)動(dòng)開發(fā)、物聯(lián)網(wǎng)云端接入、MQTT協(xié)議、json字符串等知識(shí)點(diǎn)。
基于Linux+Qt的音樂播放器項(xiàng)目
?開發(fā)平臺(tái):
華清遠(yuǎn)見stm32mp157開發(fā)板豪華套餐(開發(fā)板+仿真器+五寸屏+攝像頭+資源擴(kuò)展板+tf卡+讀卡器)
項(xiàng)目功能:
1.批量從本地導(dǎo)入歌曲到歌曲列表中。
2.清空歌曲列表。
3.刪除歌曲列表中選中的歌曲。
4.用進(jìn)度條顯示歌曲播放的進(jìn)度,并顯示時(shí)間。
5.用“播放/暫停”、“停止”、“上一曲”、“下一曲”四個(gè)按鈕對(duì)歌曲
進(jìn)行控制。
6.用滑動(dòng)器對(duì)歌曲音量進(jìn)行控制。
7.右鍵會(huì)彈出菜單,可以對(duì)程序進(jìn)行相應(yīng)的控制。
8.提取歌曲的歌詞,并解析歌詞,根據(jù)歌曲的播放進(jìn)度顯示歌詞。
?
項(xiàng)目展示:




項(xiàng)目實(shí)戰(zhàn):
源碼分析
UI 界面設(shè)計(jì)
使用三個(gè) pushbutton 來添加歌曲、刪除歌曲和清空歌曲列表。使用四個(gè)
toolbutton 來控制歌曲的播放、停止、上一曲、下一曲。使用 ListWidget 控
件來存放歌曲列表。使用 slider 來控制音量和歌曲進(jìn)度。

文件配置
因?yàn)橄旅嬉褂靡纛l播放功能,所以需要在 pro 文件引入
QT += core gui multimedia
?
歌詞類(Lyrics)
這個(gè)類通過 readLine 這個(gè)函數(shù)循環(huán)讀取每一行的歌詞,讀取到使用
analysisLyricsFile()函數(shù)進(jìn)行解析,使用正則表達(dá)式解析 lrc 歌詞文件,
獲取歌詞和時(shí)間。
?while((line=file.readLine())>0){
?analysisLyricsFile(line);
?}

lyrics.h
#ifndef LYRICS_H
#define LYRICS_H
#include <QWidget>
#include <QString>
#include <QMap>
#include <iostream>
#include <QFile>
#include <QDebug>
#include <QRegExp>
#include <QList>
#include <QRegularExpression>
#include <QRegularExpressionMatch>
using namespace std;
class Lyrics
{
private:
?QString lyricsPath;
public:
?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
Lyrics.c
#include "lyrics.h"
QList<QString> Lyrics::getListLyricsText() const{
?return listLyricsText;
}
QList<int> Lyrics::getListLyricsTime() const{
?return listLyricsTime;
}
Lyrics::Lyrics(QString lyricsPath){
?this->lyricsPath = lyricsPath;
}
bool Lyrics::readLyricsFile(QString lyricsPath)
{
?QFile file(lyricsPath);
?qDebug()<<"lyricsPath = "<<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()<<"this 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; /* 計(jì)算該時(shí)間點(diǎn)毫
秒數(shù) */
?QString currentText
=QString::fromStdString(match.captured(4).toStdString()); /*
獲取歌詞文本*/
?qDebug()<<totalTime;
?qDebug()<<currentText;
?listLyricsText.push_back(currentText);
?listLyricsTime.push_back(totalTime);
?return true;
?}
?return false;
}
?
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QMediaPlayer>
#include <QMediaPlaylist>
#include "lyrics.h"
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
?explicit Widget(QWidget *parent = 0);
?~Widget();
private slots:
?void addSongs();
?void playPause();
?void playStop();
?void playNext();
?void playPrevious();
?void posChanged(qint64 pos);
?void durChanged(qint64 dur);
?void setPos(int pos);
?void clearList();
?void delectSong();
?void volumeSilence();
?void setVol(int vol);
?void hideShow();
?void redVolume();
?void addVolume();
?void setPlayTime();
private:
?Ui::Widget *ui;
private:
?QMediaPlayer* player;
?QMediaPlaylist* playList;
?QAction* action_hideShow;
QAction* action_addSongs;
?QAction* action_playPause;
?QAction* action_stop;
?QAction* action_previous;
?QAction* action_next;
?QAction* action_addVolume;
?QAction* action_redVolume;
?QAction* action_quit;
?Lyrics lyrics;
?int lyricsID = 0;
?QString playPath;
?QString presentTime;
?QString totalTime;
protected:
?void contextMenuEvent(QContextMenuEvent* );
};
#endif // WIDGET_H
Widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QString>
#include <QStringList>
#include <QMenu>
#define BOARD_TYPE_RGB 0
#define BOARD_TYPE_MIPI 1
static int get_board_type(void)
{
?char searchText[]="-mipi050";
?int len_searchText;
?FILE *file;
?char string[128];
?int len_string;
?int i = 0;
?memset(string, 0x0, sizeof(string));
?file = fopen("/proc/device-tree/compatible", "r");
?if (file == NULL) {
?printf("fails to open /proc/device-tree/compatible\n");
?return -1;
?}
?len_searchText = strlen(searchText);
?while(fgets(string, sizeof(string), file) != 0)
?{
?len_string = strlen(string);
?for(i = 0 ; i < len_string ; i++) {
?if(strncmp(searchText, (string + i), len_searchText)
== 0) {
?fclose(file);
?return BOARD_TYPE_MIPI;
?}
?}
?}
?fclose(file);
?return BOARD_TYPE_RGB;
}
Widget::Widget(QWidget *parent) :
?QWidget(parent),
?ui(new Ui::Widget)
{
?ui->setupUi(this);
?// 適配屏幕大小
?int board_type = 0;
?board_type = get_board_type();
?qDebug()<<board_type;
?if(board_type==BOARD_TYPE_RGB)
?resize(1024,600);
?else if(board_type==BOARD_TYPE_MIPI)
?resize(480,852);
?this->setAutoFillBackground(true);
?QPalette palette;
?
palette.setBrush(QPalette::Background,QBrush(QPixmap(":/images/in
terface.jpg")));
?this->setPalette(palette);
?ui->volumeSlider->setRange(0,100);
?this->setWindowTitle(tr("hqyj 音樂播放器"));
?this->playList=new QMediaPlaylist(this);
?playList->setPlaybackMode(QMediaPlaylist::Loop);
?this->player=new QMediaPlayer(this);
player->setPlaylist(playList);
?player->setVolume(50);
?ui->volumeSlider->setValue(50);
?ui->songsList->setStyleSheet("backgroundcolor:transparent;color: white");
?ui->addSongsButton->setStyleSheet("QPushButton{background:
none;border:none;color: white}");
?ui->clearButton->setStyleSheet("QPushButton{background:
none;border:none;color: white}");
?ui->delectButton->setStyleSheet("QPushButton{background:
none;border:none;color: white}");
?ui->volumeButton->setStyleSheet("QToolButton{borderradius:5px;border-width:0px;}");
connect(ui->volumeSlider,SIGNAL(valueChanged(int)),this,SLOT(setV
ol(int)));
connect(ui->addSongsButton,SIGNAL(clicked()),this,SLOT(addSongs()
));
connect(ui->playPauseButton,SIGNAL(clicked()),this,SLOT(playPause
()));
connect(ui->stoptButton,SIGNAL(clicked()),this,SLOT(playStop()));?
connect(ui->previousButton,SIGNAL(clicked()),this,SLOT(playPrevio
us()));
connect(ui->nextButton,SIGNAL(clicked()),this,SLOT(playNext()));
connect(player,SIGNAL(durationChanged(qint64)),this,SLOT(durChang
ed(qint64)));
connect(player,SIGNAL(positionChanged(qint64)),this,SLOT(posChang
ed(qint64)));
connect(ui->processSlider,SIGNAL(valueChanged(int)),this,SLOT(set
Pos(int)));?
connect(ui->clearButton,SIGNAL(clicked()),this,SLOT(clearList()));
connect(ui->delectButton,SIGNAL(clicked()),this,SLOT(delectSong()
));?
connect(ui->volumeButton,SIGNAL(clicked()),this,SLOT(volumeSilenc
e()));
?ui->stoptButton->setStyleSheet("border:2px groove
gray;border-radius:10px;padding:2px 4px;");
?ui->playPauseButton->setStyleSheet("border:2px groove
gray;border-radius:10px;padding:2px 4px;");
?ui->previousButton->setStyleSheet("border:2px groove
gray;border-radius:10px;padding:2px 4px;");
?ui->nextButton->setStyleSheet("border:2px groove
gray;border-radius:10px;padding:2px 4px;");
?action_hideShow=new QAction(tr("隱藏/顯示窗口部件"),this);
?action_addSongs=new QAction(tr("添加本地歌曲"),this);
?action_playPause=new QAction(tr("播放/暫停"),this);
?action_stop=new QAction(tr("停止"),this);
?action_previous=new QAction(tr("上一曲"),this);
?action_next=new QAction(tr("下一曲"),this);
?action_addVolume=new QAction(tr("音量+(5%)"),this);
?action_redVolume=new QAction(tr("音量-(5%)"),this);
?action_quit=new QAction(tr("退出"),this);
connect(action_hideShow,SIGNAL(triggered()),this,SLOT(hideShow())
);
connect(action_addSongs,SIGNAL(triggered()),this,SLOT(addSongs())
);
connect(action_playPause,SIGNAL(triggered()),this,SLOT(playPause(
)));
connect(action_stop,SIGNAL(triggered()),this,SLOT(playStop()));
connect(action_previous,SIGNAL(triggered()),this,SLOT(playPreviou
s()));
connect(action_next,SIGNAL(triggered()),this,SLOT(playNext()));?
connect(action_addVolume,SIGNAL(triggered()),this,SLOT(addVolume(
)));
connect(action_redVolume,SIGNAL(triggered()),this,SLOT(redVolume(
)));
connect(action_quit,SIGNAL(triggered()),this,SLOT(close()));
}
Widget::~Widget()
{
?delete ui;
}
//每當(dāng)音量進(jìn)度條改變,會(huì)觸發(fā)這個(gè)槽函數(shù)重新設(shè)置音量大小
void Widget::setVol(int vol)
{
?player->setVolume(vol);
}
//選擇要添加的所有歌曲,添加到 QStringList 中,遍歷 QStringList 中的所
有.MP3 文件
//添加到 playList 中,并且添加到 ui 界面的 QlistWight 中
void Widget::addSongs()
{
?QStringList songsList=QFileDialog::getOpenFileNames(this,"
選擇文件",QDir::homePath(),"*.mp3");
?for(int i=0;i<songsList.size();i++)
?{
?QString song=songsList.at(i);
?qDebug()<<song;
?//歌詞存放路徑
?playPath =song.left(song.lastIndexOf("/"));
?qDebug()<<playPath;
?this->playList->addMedia(QUrl::fromLocalFile(song));
?QStringList songL=song.split('/');
?song=songL.last();
?ui->songsList->addItem(song);
?}
}
//播放/暫停
void Widget::playPause()
{
?ui->processSlider->setEnabled(true);
?if("播放"==ui->playPauseButton->text())
?{
?int index=ui->songsList->currentRow();
if(-1!=index)
?{
?//歌曲名字
?QString songname
=ui->songsList->item(index)->text().left(ui->songsList->item(inde
x)->text().lastIndexOf("."));
?playList->setCurrentIndex(index);
?player->play();
?ui->playPauseButton->setText("暫停");
ui->playPauseButton->setIcon(QIcon(":/images/pause.png"));
?// 讀取歌詞文件
if(!lyrics.readLyricsFile(playPath+"/"+songname+".lrc")){
?ui->label->setText("未檢測(cè)到歌詞文件");
?ui->label_2->setText("請(qǐng)檢查歌詞文件是否存在");
?}
?lyricsID = 0;
?}
?}
?else
?{
?player->pause();
?ui->playPauseButton->setText("播放");
ui->playPauseButton->setIcon(QIcon(":/images/play.png"));
?}
}
//播放/停止
void Widget::playStop()
{
?ui->processSlider->setEnabled(false);
?this->player->stop();
?// 清空歌詞
?ui->label->clear();
?ui->label_2->clear();
?lyrics.listLyricsText.clear();
}
//播放上一曲
void Widget::playPrevious()
{
?player->stop();
?int index=playList->currentIndex();
?if(0==index)
?index=playList->mediaCount()-1;
?else
?index--;
?playList->setCurrentIndex(index);
?ui->songsList->setCurrentRow(index);
// player->play();
?ui->playPauseButton->setText("播放");
?ui->playPauseButton->setIcon(QIcon(":/images/play.png"));
// 清空歌詞
?ui->label->clear();
?ui->label_2->clear();
?lyrics.listLyricsText.clear();
}
//播放下一曲
void Widget::playNext()
{
?player->stop();
?int index=playList->currentIndex();
?if(index==playList->mediaCount()-1)
?index=0;
?else
?index++;
?playList->setCurrentIndex(index);
?ui->songsList->setCurrentRow(index);
?ui->playPauseButton->setText("播放");
?ui->playPauseButton->setIcon(QIcon(":/images/play.png"));
// 清空歌詞
?ui->label->clear();
?ui->label_2->clear();
?lyrics.listLyricsText.clear();
}
//設(shè)置進(jìn)度條顯示范圍,并計(jì)算歌曲總時(shí)間,顯示出來
void Widget::durChanged(qint64 dur)
{
?ui->processSlider->setRange(0,dur);
?totalTime.clear();
?dur/=1000;
?totalTime+=QString::number(dur/60);
?totalTime+=':';
?if(dur%60<10)
?totalTime+='0';
?totalTime+=QString::number(dur%60);
?ui->totalTimeLabel->setText(totalTime);
}
//設(shè)置進(jìn)度條的值,并計(jì)算當(dāng)前時(shí)間,顯示出來
void Widget::posChanged(qint64 pos)
{
?presentTime.clear();
?ui->processSlider->setValue(pos);
?pos/=1000;
?presentTime+=QString::number(pos/60);
?presentTime+=':';
?if(pos%60<10)
?presentTime+='0';
?presentTime+=QString::number(pos%60);
?ui->presentTimeLabel->setText(presentTime);
?if(presentTime==totalTime)
?{
?presentTime.clear();
?player->stop();
?ui->label->clear();
?ui->label_2->clear();
?}
//根據(jù)播放進(jìn)度的改變?cè)O(shè)置播放進(jìn)度
void Widget::setPos(int pos)
{
?player->setPosition(pos);
?setPlayTime();
}
//清空播放列表
void Widget::clearList()
{
?playList->clear();
?ui->songsList->clear();
}
//在播放列表中刪除某首歌曲
void Widget::delectSong()
{
?int index=ui->songsList->currentRow();
?if(-1!=index)
?{
?ui->songsList->takeItem(index);
?playList->removeMedia(index);
?}
}
//設(shè)置有音量和靜音
void Widget::volumeSilence()
{
?if(ui->volumeButton->text()==tr("音量"))
?{
?ui->volumeButton->setText(tr("靜音"));
?ui->volumeSlider->setValue(0);
ui->volumeButton->setIcon(QIcon(":/images/silence.png"));
?}
?else
?{
?ui->volumeButton->setText(tr("音量"));
ui->volumeButton->setIcon(QIcon(":/images/volume.png"));
?ui->volumeSlider->setValue(50);
?}
}
/*鼠標(biāo)右擊事件
*每次鼠標(biāo)右擊都會(huì)顯示菜單*/
void Widget::contextMenuEvent(QContextMenuEvent*)
{
?QMenu* menu=new QMenu(this);
?menu->addAction(action_hideShow);
?menu->addAction(action_addSongs);
?menu->addSeparator();
?menu->addAction(action_playPause);
?menu->addAction(action_stop);
?menu->addAction(action_previous);
?menu->addAction(action_next);
?menu->addSeparator();
?menu->addAction(action_addVolume);
?menu->addAction(action_redVolume);
?menu->addSeparator();
?menu->addAction(action_quit);
?menu->move(cursor().pos());
?menu->show();
}
//控件隱藏/顯示
void Widget::hideShow()
{
?if(ui->songsList->isVisible())
?{
?ui->addSongsButton->setVisible(false);
?ui->clearButton->setVisible(false);
?ui->delectButton->setVisible(false);
?ui->songsList->setVisible(false);
?ui->processSlider->setVisible(false);
?ui->presentTimeLabel->setVisible(false);
?ui->totalTimeLabel->setVisible(false);
?ui->volumeButton->setVisible(false);
?ui->volumeSlider->setVisible(false);
?}
?else
?{
?ui->addSongsButton->setVisible(true);
?ui->clearButton->setVisible(true);
?ui->delectButton->setVisible(true);
?ui->songsList->setVisible(true);
?ui->processSlider->setVisible(true);
?ui->presentTimeLabel->setVisible(true);
?ui->totalTimeLabel->setVisible(true);
?ui->volumeButton->setVisible(true);
?ui->volumeSlider->setVisible(true);
?}
}
//每觸發(fā)一次,音量+5%,設(shè)置到音量進(jìn)度條上。
void Widget::addVolume()
{
?int vol=ui->volumeSlider->value();
?vol+=5;
?if(vol>100)
?vol=100;
?ui->volumeSlider->setValue(vol);
}
//每觸發(fā)一次,音量-5%,設(shè)置到音量進(jìn)度條上。
void Widget::redVolume()
{
?int vol=ui->volumeSlider->value();
?vol-=5;
?if(vol<0)
?vol=0;
?ui->volumeSlider->setValue(vol);
}
void Widget::setPlayTime()
{
if(!lyrics.getListLyricsTime().empty()&&player->position()>=lyric
s.getListLyricsTime().at(lyricsID)&&lyricsID<lyrics.getListLyrics
Time().size()-1){
ui->label->setText(lyrics.getListLyricsText().at(lyricsID));
ui->label_2->setText(lyrics.getListLyricsText().at(lyricsID+1));
?lyricsID++;
?}
}
Widget 類主要成員函數(shù)
構(gòu)造函數(shù)
在構(gòu)造函數(shù)中主要實(shí)現(xiàn)信號(hào)槽的連接,包括各種按鈕控件的信號(hào)槽連接和
QAction 類對(duì)象的信號(hào)槽連接,各種控件的樣式表的初始化。
這里用到的 QAction 類是提供了一個(gè)可以同時(shí)出現(xiàn)在菜單和工具條上的抽
象用戶界面操作,通過重寫鼠標(biāo)右擊事件,實(shí)現(xiàn)菜單的顯示和消失。
?
addSongs()
添加歌曲功能。通過 QStringList 類實(shí)例化對(duì)象 songsList,獲取要添加
的歌曲的路徑和文件名。遍歷 songsList,將列表里的每一首歌曲依次添加到
ui 界面的 listwidget 控件里。在此函數(shù)里還獲取歌詞存放的路徑(默認(rèn)歌詞
和歌曲文件存放路徑相同)。
?
playPause()
播放和暫停功能。使用 QMediaPlayer 類實(shí)例化 player 對(duì)象,
QMediaPlaylist 類實(shí)例化 playList 對(duì)象;從 ui 界面 listwidget 控件獲取歌單
添加到 playList;play 對(duì)象從 playList 中選擇其中一首歌,調(diào)用對(duì)象 play 函
數(shù),實(shí)現(xiàn)歌曲的播放。調(diào)用 pause(),實(shí)現(xiàn)歌曲的暫停。
?
playNext()
下一曲。通過 index =playList->currentIndex()函數(shù)獲取歌曲列表此時(shí)
的歌曲序號(hào),使序號(hào)+1 ,重新設(shè)置歌曲列表此時(shí)選中歌曲序號(hào)
playList->setCurrentIndex(index);實(shí)現(xiàn)下一曲的播放。上一曲使序號(hào)減一就
好了。
?
durChanged()
void Widget::durChanged(qint64 dur)
{
?ui->processSlider->setRange(0,dur);
?totalTime.clear();
?dur/=1000;
?totalTime+=QString::number(dur/60);
?totalTime+=':';
?if(dur%60<10)
?totalTime+='0';
?totalTime+=QString::number(dur%60);
?ui->totalTimeLabel->setText(totalTime);
}
?設(shè)置進(jìn)度條顯示范圍,并計(jì)算歌曲總時(shí)間,顯示出來。
?
?setPlayTime()
?在歌詞顯示欄里設(shè)置讀取到的歌詞。
void Widget::setPlayTime()
{
if(!lyrics.getListLyricsTime().empty()&&player->position()>=lyric
s.getListLyricsTime().at(lyricsID)&&lyricsID<lyrics.getListLyrics
Time().size()-1){
ui->label->setText(lyrics.getListLyricsText().at(lyricsID));
ui->label_2->setText(lyrics.getListLyricsText().at(lyricsID+1));
?lyricsID++;
?}
}
?contextMenuEvent(QContextMenuEvent*)
每次鼠標(biāo)右擊,都會(huì)實(shí)例化一個(gè) menu 對(duì)象 QMenu* menu=new
QMenu(this);然后向菜單對(duì)象添加在構(gòu)造函數(shù)實(shí)例化的 QAction 對(duì)象,然后顯
示菜單。
實(shí)驗(yàn)源碼
源碼路徑【1_音樂播放器\實(shí)驗(yàn)源碼\1_music_player】
?
?注意事項(xiàng)
1.在 ubuntu 上運(yùn)行時(shí),lrc 歌詞文件要使用 utf-8 編碼,否則讀取歌詞時(shí)會(huì)
出現(xiàn)亂碼。

2.向開發(fā)板拷貝歌曲和歌詞時(shí),歌詞需要使用 dos2unix 命令,將 DOS 格式
的文本文件轉(zhuǎn)換為 UNIX 格式。(如果不轉(zhuǎn)換,會(huì)有識(shí)別不了的字符,因?yàn)殚_發(fā)
板的 ubuntu 沒有自動(dòng)轉(zhuǎn)換的功能),然后使用 scp 命令拷貝到開發(fā)板。
dos2unix wukong.lrc

sudo scp wukong.mp3 wukong.lrc root@192.168.10.128:~

3.在開發(fā)板運(yùn)行時(shí),需要導(dǎo)入中文字庫,否則會(huì)因?yàn)樽R(shí)別不了中文歌詞程
序出錯(cuò)。
將【1_音樂播放器\工具軟件\wqy-zenhei-0.9.47-nightlybuild.tar.gz 或 wqyzenhei-0.8.38-1.tar.gz】復(fù)制到 ubuntu 下。并使用 scp 命令將文件拷貝到開發(fā)板
的 usr/share/fonts 目錄下,使用 tar 命令解壓后即可。
linux@ubuntu:~$ scp wqy-zenhei-0.8.38-1.tar.gz
root@192.168.10.128:/usr/share/fonts/

4.如果使用 mipi 五寸屏運(yùn)行此項(xiàng)目,需要進(jìn)行屏幕旋轉(zhuǎn)以適應(yīng)屏幕,具體
步驟如下:
在/etc/profile.d/qt-eglfs.sh 添加環(huán)境變量如下:


下面變量的 event0 設(shè)備需要填實(shí)際的觸摸屏設(shè)備
這里即填 event0
export QT_QPA_EGLFS_ROTATION=90
export QT_QPA_EGLFS_NO_LIBINPUT=1
export
QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=90