Reproductor de música QT integrado basado en mplayer

1. Implementar funciones

2. Interfaz de reproducción de música

2.1 Programa de interfaz 

2.1.1 Inicialización del control de interfaz

2.1.2 Programa de estilo de control

3. Interfaz de lista de canciones

3.1.1 Definir el puntero de objeto QListWidge en widget.h

3.1.2 Agregar inicialización de QlistWidge en la función memberInit

3.1.3 Establecer su estilo en la función setMusicPlayStyle

4. Implementación de la función de reproducción de música.

4.1 Obtener canciones locales

4.1.1 Mostrar lista de canciones

5. Qprocess implementa MPlayer

5.1 Proceso de uso de QT

5.2 QProcess llama al método MPlayer

6. Lista de comandos de Mplayer

7. Implementar funciones de reproducción y pausa. 

7.1 Inicialización del jugador

7.2 Implementación de la función de reproducción

7.3 Implementación de la función del botón de reproducción

8. Obtenga el tiempo total y la hora actual.

8.1 Agregar funciones de ranura relevantes a la función MaplayerInit

8.2 Al comienzo de la función de ranura de reproducción, envíe el comando para obtener el tiempo total

8.3 Obtener el tiempo total y el tiempo actual en la función de ranura de datos

8.4 Enviar el comando para obtener la hora actual en la función de ranura del temporizador

8.5 Iniciar el cronómetro en la función playMusic

8.6 Agregar interruptor de temporizador en la función updatePlayPauseBtnStateSlot

9. Función de reproducción con doble clic

9.1 Asociación de señales y slots

9.2 Funciones de ranura de escritura

10. Configuración de volumen

10.1 Asociación de señales y slots

10.2 Implementar la función de ranura

11. Cambio de canción

11.1 Configuración del modo de reproducción

11.1.1 Usar enumeración para definir el modo de reproducción (enumeración definida dentro de la clase)

11.1.2 Asociación de señales y slots

11.1.3 Implementar la función de ranura

11.2 Canción anterior

11.2.1 Asociación de señales y slots

11.2.2 Implementar la función de ranura

11.2.3 La función de ranura envía contenido de reproducción personalizado

11.2.4 Asociación de señales y ranuras personalizadas

11.2.5 Implementar funciones personalizadas de señal y ranura para actualizar y mostrar el contenido de reproducción

11.3 Conmutación automática

11.3.1 Funciones de ranura asociadas

11.3.2 Implementar la función de ranura

12. Avance rápido y rebobinado rápido

12.1 Asociación de señales y ranuras del control deslizante de arrastre

12.2 Implementar el arrastre de señales y ranuras del control deslizante

12.3 Asociación de la señal de la corredera de liberación a la ranura

12.4 Realice la señal y la ranura para soltar el control deslizante

13. Ocultar jugador

13.1 Funciones de ranura asociadas

13.2 Implementar la función de ranura

14. Guardar canciones

14.1 Definir puntero de objeto de configuración

14.2 Agregar canciones para guardar en la lista

14.3 Cargar y guardar canciones

15. Eliminar canciones


1. Implementar funciones

Las funciones implementadas por la reproducción de música son:
1 ) Función de reproducción / pausa,
2 ) Canción anterior / siguiente canción,
3 ) Establezca el volumen,
4 ) Establecer el modo de reproducción,
5 ) Haga doble clic en el nombre de la canción en la lista de canciones para reproducir la música.
6 ) Al reproducir música, se puede mostrar el nombre de la canción que se va a reproducir.
7 ) Muestra el tiempo de reproducción actual y el tiempo total de la música actual.
8 ) Desliza para cambiar el progreso de reproducción de la música.

2. Interfaz de reproducción de música

   El diseño de la interfaz se establece mediante la interfaz UI y no se utiliza ningún código de programa para el diseño. En el programa, por supuesto, la interfaz de código del programa también se puede utilizar para el diseño. La parte aquí es el diseño del código del programa ui, y la lista de reproducción utiliza el diseño del programa.

2.1 Programa de interfaz 

2.1.1 Inicialización del control de interfaz

//控件初始化
void Widget::memberInit()
{
 QIcon scanIcon(QPixmap(":/music/resource/player/player_icon/open.png"));
 QIcon palyIcon(QPixmap(":/music/resource/player/player_icon/list.png"));
 ui->scanLocalFileBtn->setIconSize(QSize(40,40));
 ui->scanLocalFileBtn->setIcon(scanIcon);
 ui->showPlayListBtn->setIconSize(QSize(40,40));
 ui->showPlayListBtn->setIcon(palyIcon);
 QIcon sequenceIcon(QPixmap(":/music/resource/player/player_icon/列表循
环.png"));
 QIcon onceIcon(QPixmap(":/music/resource/player/player_icon/单曲循环.png"));
 QIcon rangeIcon(QPixmap(":/music/resource/player/player_icon/随机播放.png"));
 QIcon onceSignle(QPixmap(":/music/resource/player/player_icon/单曲一次.png"));
 QIcon stepPlay(QPixmap(":/music/resource/player/player_icon/顺序播放.png"));
 ui->playModelCbox->addItem(stepPlay,"顺序播放");
 ui->playModelCbox->addItem(onceSignle,"单曲一次");
 ui->playModelCbox->addItem(onceIcon,"单曲循环");
 ui->playModelCbox->addItem(sequenceIcon,"循环播放");
 ui->playModelCbox->addItem(rangeIcon,"随机播放");
 //音量滑条的范围 40~100 声音的范围(测试 40 以上有声音)
 ui->volumeSlider->setRange(0,100);
 //设置音量滑条的初始值为 70
ui->volumeSlider->setValue(50);
}

2.1.2 Programa de estilo de control

void Widget::setMusicPlayStyle()
{
//设置播放器背景图片 通过调色板实现
 QString musicBack = ":/music/resource/player/播放器背景.png";
 playerPalette.setBrush(QPalette::Background,QBrush(QPixmap(musicBack)));
 this->setPalette(playerPalette);
 this->setAutoFillBackground(true);
 //上一首
 ui->preSongBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/prev.png);"
 "border-radius:10px;"
 );
 //下一首
 ui->nextSongBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/next.png);"
 "border-radius:10px;"
 );
 //播放
 ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/play.png);"
 "border-radius:10px;"
 );
 //播放模式
 ui->playModelCbox->setStyleSheet("background: url(:/music/resource/player/播放
器背景.png);"
 "border: 1px solid gray;"
 "border-radius:5px;"
 "min-width: 6em;"
 "font: 15px;"
 "color: #FFFFFF;"
 );
 //改变播放滑条和音量滑条的样式表
 
ui->playProgressSlider->setStyleSheet("QSlider::groove:horizontal{border:0px;height
:4px;}"
 "QSlider::subpage:horizontal{background:red;}"
 "QSlider::addpage:horizontal{background:lightgray;}"
 
"QSlider::handle:horizontal{background:white;width:10px;border-radius:5px;margin:-
3px 0px -3px 0px;}");
ui->volumeSlider->setStyleSheet( "QSlider::groove:horizontal{border:0px;height:4px;
}"
 "QSlider::subpage:horizontal{background:red;}"
 "QSlider::addpage:horizontal{background:lightgray;}"
 
"QSlider::handle:horizontal{background:white;width:10px;border-radius:5px;margin:-
3px 0px -3px 0px;}");
 //扫描歌曲 播放列表 返回 关闭 透明
 ui->scanLocalFileBtn->setStyleSheet("background: transparent;"
 "border: 1px solid gray;"
 "border-radius:6px;"
 "color: #FFFFFF;"
 "font:16px;"
 "min-width: 4em;"
 );
 ui->showPlayListBtn->setStyleSheet("background: transparent;"
 "border: 1px solid gray;"
 "border-radius:6px;"
 "color: #FFFFFF;"
 "font:16px;"
 "min-width: 4em;"
 );
 ui->closeBtn->setStyleSheet("background: transparent;"
 "border: 1px solid gray;"
 "border-radius:6px;"
 "color: #FFFFFF;"
 "font:16px;"
 "min-width: 4em;"
 );
 ui->blackBtn->setStyleSheet("background: transparent;"
 "border: 1px solid gray;"
 "border-radius:6px;"
 "color: #FFFFFF;"
 "font:16px;"
 "min-width: 4em;"
 );
 //歌曲名
 ui->songNameLb->setStyleSheet("font:18px;""color:#FFFFFF;");

3. Interfaz de lista de canciones

 Utilice un programa para crear un control QListWidget para mostrar una lista de canciones.

3.1.1  Definir el puntero del objeto QListWidge en widget.h

QListWidget *showPlayList;

3.1.2  Agregar inicialización de QlistWidge en la función memberInit

 //显示列表初始化
 showPlayList = new QListWidget; //列表显示 --通过程序创建控制
 showPlayList->setMinimumSize(400,500);
 showPlayList->setMaximumSize(400,500);
 showPlayList->setWindowTitle("播放列表");
 showPlayList->setWindowIcon(QIcon(QPixmap(":/music/resource/image/music.png")));
 //设置显示列表显示的位置跟音乐部件的显示位置同一个高度,在音乐部件的后面,x 坐
标为音乐部件的宽度
 this->move(500,300);
 showPlayList->move(this->width()+510,this->y());
playListBtnState = true; //false 隐藏,true 显示
 showPlayList->show();

3.1.3  Establecer su estilo en la función setMusicPlayStyle

 //设置显示列表的背景
 showPlayList->setStyleSheet("QListWidget{color:#D4D4D4;"
 "font:17px;"
 "backgroundimage:url(:/music/resource/player/playerlist/播放器列表背景.png);}");

4. Implementación de la función de reproducción de música.

  Debido a que la reproducción de música de Qt se basa en la plataforma Linux, si se implementa usando el reproductor multimedia existente QMediaPlayer proporcionado por Qt , solo se puede implementar en la plataforma Windows y no es compatible con la plataforma Linux porque el reproductor multimedia Qt5 usa QMediaPlayer. y QMediaPlayer usa el backend de gstreamer para reproducir medios, y gstreamer no es portátil para armar . Entonces finalmente decidí usar QProcess para ajustar directamente MPlayer en Qt5 para implementar la función de reproducción de música. Estas son las funciones principales utilizadas en el programa.

4.1 Obtener canciones locales

/****************************************************
* 函数原型:void getLocalFileSots()
* 函数功能:获取本地音乐文件槽函数
*****************************************************/
void Widget::getLocalFileSots()
{
 //获取选择的文件目录名
 QString fileNameDir = QFileDialog::getExistingDirectory(this,"选择音乐文件
","../music");
 if(fileNameDir.isEmpty())
 {
 return;
 }
 //对目录进行扫描操作,需要目录类,利用目录路径构造目录类对象
 //1.利用 带路径的目录名 构造目录类对象
 QDir dir(fileNameDir);
 //2.编写 过滤的文件格式
 QStringList formatList;
 formatList << "*.mp3" << "*.mp4" << "*.wma";
 //3. 创建文件信息列表
 //QFileInfoList infoList;
 //4. 按照过滤的文件格式扫描文件,选择符合格式的文件
 infoList = dir.entryInfoList(formatList);
 if(infoList.isEmpty())
 {
 return;
 }
 //显示列表显示歌名的时候,前面加显示图标,显示图标的位置
 QIcon musicMap(QPixmap(":/music/resource/player/playerlist/音符 1.png"));
 for(int i = 0; i < infoList.count(); i++)
 {
 //需要检测是否重复
 //媒体播放内容列表需要带路径的文件名
 playListString << infoList[i].filePath();
 //显示给用户的列表只需要显示文件名,并在显示列表前面加图标
 QListWidgetItem *songNameList = new
QListWidgetItem(musicMap,infoList[i].fileName());
songNameList->setSizeHint(QSize(400,40));
 showPlayList->addItem(songNameList);
 //打印文件路径 和文件名
 //qDebug() << infoList[i].fileName(); //不带路径的文件名
 //qDebug() << infoList[i].filePath(); //带路径的文件名
 }
 showPlayList->setCurrentRow(0);
}

4.1.1 Mostrar lista de canciones

/****************************************************dddddd
* 函数原型:void updatePlayFileListBtnStateSlots()
* 函数功能:更新显示文件列表的状态
* 该显示文件列表要么显示,要么被隐藏
* 说明:
* playListBtnState == true 显示列表
* playListBtnState == false 隐藏列表
*****************************************************/
void Widget::updatePlayFileListBtnStateSlots()
{
 //跟以前状态相反
 playListBtnState = !playListBtnState;
 QIcon showIcon(QPixmap(":/music/resource/player/player_icon/列表.png"));
 QIcon hideIcon(QPixmap(":/music/resource/player/player_icon/隐藏列表.png"));
 switch (playListBtnState)
 {
 case true:
 showPlayList->show(); //显示
 ui->showPlayListBtn->setIcon(hideIcon);
 break;
 case false:
 showPlayList->hide(); //隐藏
 ui->showPlayListBtn->setIcon(showIcon);
 break;
 }
}

5. Qprocess implementa MPlayer

5.1 Proceso de uso de QT

 programa:

Widget::Widget(QWidget *parent) :
 QWidget(parent),
 ui(new Ui::Widget)
{
 ui->setupUi(this);
 myProcess = new QProcess(this);
 connect(myProcess,SIGNAL(readyRead()),this,SLOT(doSlotProcessReadyRead()));
}

void Widget::on_btnExec_clicked()
{
 QString cmd = ui->lEditCmd->text();
 QString arg = ui->lEditArg->text();
 QStringList arrayArg = arg.split(" "); //获取所有的参数
 myProcess->start(cmd,arrayArg);
}

void Widget::doSlotProcessReadyRead(){
 while(!myProcess->atEnd()){
 //readLine 返回的是 QByteArray,转为 QString ,replace("\n","")去掉\n
 QString str = QString(myProcess->readLine()).replace("\n","");
 ui->textEdit->append(str);
 }
}

5.2   QProcess llama al método MPlayer

Solo necesitamos crear un nuevo QProcess y luego iniciar el hilo de mplayer a través del método de inicio de QProcess , de la siguiente manera:
proceso = nuevo QProcess();
argumentos QStringList;
args << "-slave"; // Usar modo esclavo
args << "-quiet"; // No genera información redundante
_process->start("mplayer", args); // Inicia el proceso y pasa los parámetros args

 Nota: El mplayer aquí necesita agregar la ruta absoluta, que es la ubicación donde está almacenado su mplayer actual .

Entonces, de esta manera, podrás iniciar mplayer . Si queremos controlar mplayer , podemos usar el método de escritura de QProcess para escribir comandos en mplayer, como los siguientes:
proceso->escribir("pausa\n");

 Si desea leer el mensaje enviado por mplayer , utilice el método readLine de QProcess de la siguiente manera:

_proceso->readLine(datos,200);

 De esta manera, podemos leer una línea de información enviada por mplayer y luego solo necesitamos analizar estos datos .

6. Lista de comandos de Mplayer

cargar nombre de archivo // cargar el nombre del archivo multimedia
volumen 100 1 // Establece el volumen, el volumen medio es 0-100
seek 50 1 // Establece el progreso, 50 representa el tamaño del progreso ( porcentaje ) , 0-100 //0 es una búsqueda relativa de +/- <valor> segundos (predeterminado).
//1 es una búsqueda de <valor> % en la película.
//2 es una búsqueda de una posición absoluta de <valor> segundos.
silencio 1/0 // interruptor de silencio
pausar // reproducir / pausar
get_time_length // Obtiene el tiempo total de reproducción del archivo, en segundos
buscar valor // posicionamiento, valor es el número de segundos
get_percent_pos // Obtener el porcentaje de reproducción
get_time_pos // Obtiene la posición de juego actual en segundos
get_file_name // Obtiene el nombre del archivo multimedia que se está reproduciendo actualmente
get_meta_album // Obtener el álbum
get_meta_artist // Consigue el artista
get_meta_comment // Obtener comentarios
get_meta_genre // Obtener el género
get_meta_title // Obtener el título
get_meta_year // Obtener el año

7. Implementar funciones de reproducción y pausa. 

7.1 Inicialización del jugador

En el archivo de encabezado musicplay , después de agregar la declaración de los miembros relevantes y luego implementarla en el archivo fuente, lo primero es inicializar el reproductor de la siguiente manera:
//初始化播放器
void Widget::MaplayerInit()
{
 //创建播放进程
 playProcess = new QProcess(this);
 playProcess->setProcessChannelMode(QProcess::MergedChannels);
 program = "/usr/bin/mplayer"; //X86 架构下
 //program = "/usr/local/bin/mplayer"; //mplayer 命令路径,一定要正确,不然无法
播放 –ARM 架构
 playState = false; //播放状态
 playBtnState = false; //播放按钮状态
playIndex = 0; //播放内容下标,跟显示列表的内容要保持一致
}

7.2 Implementación de la función de reproducción

void Widget::playMusic()
{
 //如果没有加载播放内容
 playProcess->close();
 args.clear();
 args << "-slave"; //使用 slave 模式
 args << "-quiet"; //不要输出冗余信息
 args << playListString[playIndex];
 qDebug() << " playListString[playIndex]: " << playListString[playIndex];
 QString str = "正在播放: " + showPlayList->currentItem()->text();
 ui->songNameLb->setText(str); //显示正在播放的音乐
playProcess->start(program,args); //开始播放
 playProcess->write("volume 70 1\n");
playState = true;
}

7.3 Implementación de la función del botón de reproducción

/****************************************************
* 函数原型:void updatePlayPauseBtnStateSlot()
* 函数功能:更新播放暂停按钮状态
*****************************************************/
void Widget::updatePlayPauseBtnStateSlot()
{
 playBtnState = !playBtnState;
 switch(playBtnState)
 {
 case true:
 if(!playState) {
 playMusic();
 }
 else
 {
 playProcess->write("pause\n");
 }
 ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/暂停.png);"
 "border-radius:10px;"
 );
 break;
 case false:
 playProcess->write("pause\n");
 ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/播放.png);"
 "border-radius:10px;"
 );
 break;
}
}

8. Obtenga el tiempo total y la hora actual.

8.1  Agregar funciones de ranura relacionadas a la función MaplayerInit

//初始化播放器
void Widget::MaplayerInit()
{
 //关联相关的信号,进程启动成功,出错,有数据可读等
connect(playProcess,SIGNAL(started()),this,SLOT(onStartedSlot()));
connect(playProcess,SIGNAL(error(QProcess::ProcessError)),this,SLOT(onErrorSlot()))
;
connect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadDataSlot()));
connect(playProcess,SIGNAL(finished(int)),this,SLOT(onPlayProcessFinishedSlot()));
//创建定时器--定时器的主要功能, 就是用于定时获取当前音乐的播放时间, 然后进行
转换为当前的播放时间
timer = new QTimer(this);
 connect(timer,SIGNAL(timeout()),this,SLOT(onTimeoutSlot()));
}

8.2  Al comienzo de la función de ranura de reproducción, envíe el comando para obtener el tiempo total

void Widget::onStartedSlot()
{
 qDebug() << "准备播放";
 //获取播放文件的长度以毫秒为单位
 playProcess->write("get_time_length\n");
}

8.3  Obtener el tiempo total y el tiempo actual en la función de ranura de datos

void Widget::onReadDataSlot()
{
 while (playProcess->bytesAvailable()) {
 QByteArray arr = playProcess->readLine();
 QString str = QString::fromLocal8Bit(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;
 tlength = m * 60 + s;
 qDebug() << "tlength " << tlength;
 //设置播放进度的总数值
 ui->playProgressSlider->setMinimum(0);
 ui->playProgressSlider->setMaximum(tlength);
 ui->playProgressSlider->setSingleStep(1);
 QString timeLength;
 timeLength.sprintf("%02d:%02d",m,s);
 ui->totleTimeLb->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 m = t / 60;
 int s = (int)(t+0.5) % 60; //四舍五入防止少时间
 QString timePos;
 timePos.sprintf("%02d:%02d",m,s);
 ui->currentTimeLb->setText(timePos);
 int now = (m * 60 + s);
 //double slider = now *100 /tlength;
 //设置播放进度当前滑条的值
 ui->playProgressSlider->setValue(now);
 }
 }
}

8.4  Enviar el comando para obtener la hora actual en la función de ranura del temporizador

void Widget::onTimeoutSlot()
{
 //获取当前播放的位置,以秒为单位
 playProcess->write("get_time_pos\n");
}

8.5   Iniciar el cronómetro en la función playMusic

void Widget::playMusic()
{
 …..
 // 定时器开启
timer->start(100);
}

8.6  Agregar interruptor de temporizador en la función updatePlayPauseBtnStateSlot

void Widget::updatePlayPauseBtnStateSlot()
{
 playBtnState = !playBtnState;
 switch(playBtnState)
 {
 case true:
 if(!playState) {
 playMusic(); //第一次播放
 }
 else
 {
 playProcess->write("pause\n");
timer->start(); →暂停后再次播放时启动定时器
 }
…
 break;
 case false:
 playProcess->write("pause\n");
 timer->stop();→暂停播放时关闭定时器
 ….
 break;
}}

9. Función de reproducción con doble clic

9.1 Asociación de señales y slots

//显示列表用户双击信号关联指定音乐文件的槽函数
connect(showPlayList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(doubleClickedToPl
ayerMusicSlots()));

9.2 Funciones de ranura de escritura

/****************************************************
* 函数原型:void loadMusicToPlayerSlots()
* 函数功能:加载指定音乐到播放列表槽函数
* 用户通过双击选择需要播放的音乐
*****************************************************/
void Widget::doubleClickedToPlayerMusicSlots()
{
 //获取显示列表的当前行
 int row = showPlayList->currentRow();
 playIndex = row;
 playState = false; //双击之后需要播放音乐
 playBtnState = false; //无论之前是什么状态,双击之后必须播放
 updatePlayPauseBtnStateSlot(); //更新播放暂停按钮—实现播放
}

10. Configuración de volumen

10.1 Asociación de señales y slots

//音量改变信号
connect(ui->volumeSlider,SIGNAL(sliderMoved(int)),this,SLOT(setVolumeSlot(int)));

10.2 Implementar la función de ranura

void Widget::setVolumeSlot(int volume)
{
 QString str = QString("volume ");
 if(playProcess->isOpen())
 {
 QString buf;
 buf.setNum(volume);
str += buf + " 1\n";
 //playProcess->write("volume %d 1\n",volume);
 playProcess->write(str.toLocal8Bit());
 }
}

11. Cambio de canción

11.1 Configuración del modo de reproducción

11.1.1  Usar enumeración para definir el modo de reproducción (enumeración definida dentro de la clase)

public:
 typedef enum
 {
 ListPlay = 0, //顺序播放
 SingleSongOnce = 1, //单曲一次
 SingleSongLoop = 2, //单曲循环
 PlayListLoop = 3, //列表循环
 RandomPlay = 4, //随机播放
}PlayModel;

11.1.2 Asociación de señales y slots

//模式选择关联 更新播放按钮槽函数
connect(ui->playModelCbox,SIGNAL(currentIndexChanged(int)),this,SLOT(updatePlayMode
Slots(int)));

11.1.3 Implementar la función de ranura

/****************************************************
* 函数原型:void updatePlayModeSlots(int index)
* 函数功能:更新播放模式,获取用户选择的模式
* 用户选择的模式跟系统的模式顺序关联
*****************************************************/
void Widget::updatePlayModeSlots(int index)
{
 switch (index)
 {
 case 0:
 //顺序播放
 playModel = ListPlay;
 break;
 case 1:
 //单曲一次
 playModel = SingleSongOnce;
 break;
 case 2:
 //单曲循环
 playModel = SingleSongLoop;
 break;
case 3:
 //循环播放
 playModel = PlayListLoop;
 break;
 case 4:
 //随机播放
 playModel = RandomPlay;
 break;
 }
}

11.2 Canción anterior

11.2.1 Asociación de señales y slots

//上一首
connect(ui->preSongBtn,SIGNAL(clicked(bool)),this,SLOT(playPrevSongSlot()));

11.2.2 Implementar la función de ranura

void Widget::playPrevSongSlot()
{
if(playIndex > 0)
 {
 if(playModel == RandomPlay) //随机播放
 {
 qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));//获取时间因子
 playIndex = qrand() %(playListString.count()-1); //产生
playListString.count()-1 以内的随机数
 }
 else
 {
 playIndex--;
 }
 playState = false; //点击上一首之后需要播放音乐
 playBtnState = false; //无论之前是什么状态,点击上一首之后必须播放
 updatePlayPauseBtnStateSlot();
 //发送播放内容改变信号
 emit playConcentChanged(playIndex);
 }else{//回到最后一首
 if(playModel == RandomPlay) //随机播放
 {
 qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));//获取时间因子
 playIndex = qrand() %(playListString.count()-1); //产生
playListString.count()-1 以内的随机数
 }
 else
 {
 playIndex=playListString.count()-1;
}
 playState = false; //点击上一首之后需要播放音乐
 playBtnState = false; //无论之前是什么状态,点击上一首之后必须播放
 updatePlayPauseBtnStateSlot();
 //发送播放内容改变信号
 emit playConcentChanged(playIndex);
 }

11.2.3 La función de ranura envía contenido de reproducción personalizado

signals:
 void playConcentChanged(int index); //播放内容改变信号,播放内容改变,发送改变的
下标

11.2.4 Asociación de señales y ranuras personalizadas

//媒体内容列表行改变(下一首、上一首、一首歌播放结束) 关联 显示列表行改变槽函数
connect(this,SIGNAL(playConcentChanged(int)),this,SLOT(updateShowPlayListRow(int)))
;
//双击当前行 播放内容改变(下一首、上一首、一首歌播放结束) 歌曲名更新
connect(showPlayList,SIGNAL(doubleClicked(QModelIndex)),this,SLOT(updateSongTitleSl
ot()));

11.2.5  Implementar funciones personalizadas de señal y ranura para actualizar y mostrar el contenido de reproducción

/****************************************************
* 函数原型:void updateShowPlayListRow(int row)
* 函数功能:更新显示列表行的槽函数
* 根据播放内容列表的行改变更新显示列表的行
* 播放内容列表 0 行对应播放列表第一行
*****************************************************/
void Widget::updateShowPlayListRow(int row)
{
 showPlayList->setCurrentRow(row+1);
 //更新歌曲标题
 //内容列表 改变, 歌曲名更新
 updateSongTitleSlot();
}
//内容列表 改变, 歌曲名更新槽函数
void Widget::updateSongTitleSlot()
{
 //当前项的文本
 QString name = showPlayList->currentItem()->text();
 QString str = "正在播放: " + name;
 ui->songNameLb->setText(str);
}

El mismo principio se aplica a la siguiente canción.

11.3 Conmutación automática

Después de reproducir una canción, se deben realizar los ajustes correspondientes según el modo de reproducción actual.

11.3.1 Funciones de ranura asociadas

connect(playProcess,SIGNAL(finished(int)),this,SLOT(onPlayProcessFinishedSlot()));

11.3.2 Implementar la función de ranura

void Widget::onPlayProcessFinishedSlot()
{
 //定时器关闭
 timer->stop();
 playBtnState = false;
 //更新播放暂停按钮
 switch(playBtnState)
{
 case true:
 ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/暂停.png);"
 "border-radius:10px;"
 );
 break;
 case false:
 ui->playBtn->setStyleSheet("border-image:
url(:/music/resource/player/player_icon/播放.png);"
 "border-radius:10px;"
 );
 break;
 }
 if(ui->playProgressSlider->value() != ui->playProgressSlider->maximum())
 {
 return;
 }
 //如果 if 语句不成立,则说明,一首歌曲播放完成,而不是播放到一半点击下一首
 //qDebug() << "一首歌曲播放完成.......";
 //一首歌曲播放完成之后,根据播放模式选择要播放的音乐
 switch (playModel)
 {
 case ListPlay: //顺序播
 if(playIndex == playListString.count()-1)
 {
 //播放滑条清空。。。。。。
 ui->playProgressSlider->setValue(0);
 playState = false; //播放当前播放的内容,则停止播放
 ui->songNameLb->setText("无歌曲");//显示无歌曲名
 //当前时间和总共时间清零
 ui->currentTimeLb->setText("00:00");
 ui->totleTimeLb->setText("00:00");
 //如果点击播放,默认播放的是第一首歌曲
 playIndex = 0;
 //设置当前行为第行
 showPlayList->setCurrentRow(playIndex);
 return;
 }
 playIndex++;
 break;
 case SingleSongOnce: //单曲一次
 //播放当前播放的内容,则停止播放
 ui->playProgressSlider->setValue(0);
ui->songNameLb->setText("无歌曲");//显示无歌曲名
 //当前时间和总共时间清零
 ui->currentTimeLb->setText("00:00");
 ui->totleTimeLb->setText("00:00");
 playState = false; //点击播放的时候,可以继续以当前的内容进行播放
 return;
 case SingleSongLoop: //单曲循环
 break;
 case PlayListLoop: //循环播放
 if(playIndex == playListString.count()-1)
 {
 playIndex = 0;
 }
 playIndex++;
 break;
 case RandomPlay: //随机播放
 qsrand(QTime(0,0,0).msecsTo(QTime::currentTime()));//获取时间因子
 playIndex = qrand() %(playListString.count()-1);
 break;
 }
 playState = false; //点击下一首之后需要播放音乐
 playBtnState = false; //无论之前是什么状态,点击下一首之后必须播放
 updatePlayPauseBtnStateSlot();
 //发送播放内容改变信号
emit playConcentChanged(playIndex);
}

12. Avance rápido y rebobinado rápido

12.1 Asociación de señales y ranuras del control deslizante de arrastre

//快进快退拖动槽函数
connect(ui->playProgressSlider,SIGNAL(sliderMoved(int)),this,SLOT(updateSongSeekSlo
t(int)));

12.2 Implementar el arrastre de señales y ranuras del control deslizante

void Widget::updateSongSeekSlot(int seek)
{
disconnect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadDataSl
ot()));//断开读取数据的槽,避免拖动时重新设置了滑块的值
 moveSliderVal = seek; //记录滑块的值
}

12.3 Asociación de la señal de la corredera de liberación a la ranura

//快进快退松开槽函数
connect(ui->playProgressSlider,SIGNAL(sliderReleased()),this,SLOT(updateSongSeekRel
easedSlot()));

12.4 Realice la señal y la ranura para soltar el control deslizante

void Widget::updateSongSeekReleasedSlot()
{
 qDebug()<< "Released";
 int seek = (moveSliderVal * 100) / tlength;//百分比的进度
 playProcess->write("pause\n");
 QString str = QString("seek ");
 if(playProcess->isOpen())
 {
 QString buf;
 buf.setNum(seek);
 str += buf + " 1\n";
 playProcess->write(str.toLocal8Bit());
} 
connect(playProcess,SIGNAL(readyReadStandardOutput()),this,SLOT(onReadDataSlot()));
重新连接读取数据的槽
}
14.13 关闭音乐 
1. 关闭事件
void Widget::closeEvent(QCloseEvent *event)
{
 //点击部件的叉号的时候,会自动调用关闭事件函数
 //在关闭事件函数里面做一次释放
 //进程关闭
 playProcess->close();
 //清空音乐显示列表
 showPlayList->clear();
 //清空播放内容列表
 playListString.clear();
 //显示列表部件关闭
 showPlayList->close();
 //发送销毁信号
 qDebug() << "关闭程序。。。。。。";
 //emit musicDestroyed(true);
}

13. Ocultar jugador

13.1 Funciones de ranura asociadas

connect(ui->hideBtn,SIGNAL(clicked(bool)),this,SLOT(hideMusicPlayerSlots()));

13.2 Implementar la función de ranura

void Widget::hideMusicPlayerSlots()
{
 //设置显示列表状态
 playListBtnState = true;
 //更新显示列表状态
 updatePlayFileListBtnStateSlots();
this->hide();
}

14. Guardar canciones

Los usuarios suelen tener estos requisitos para las aplicaciones: exigir que recuerden su configuración , como el tamaño de la ventana, la ubicación, algunas otras configuraciones y otra utilizada con frecuencia, que son los archivos recientes , etc. Todo esto se puede lograr a través de Qsettings
Cuando creamos un objeto Qsettings , debemos pasarle dos parámetros: el primero es el nombre de su empresa u organización y el segundo es el nombre de su aplicación.

14.1 Definir puntero de objeto de configuración

QSettings *configIniWrite; //配置文件写指针
QSettings *configIniRead; //配置文件读指针
QSettings *configIniDelete; //配置文件删除指针

14.2 Agregar canciones para guardar en la lista

void Widget::getLocalFileSots()
{
…
configIniWrite = new QSettings("PlayList.ini", QSettings::IniFormat);
 for(int i = 0; i < infoList.count(); i++)
 {
 …
 //保存当前歌曲
 configIniWrite->setValue("/song/"+ QString::number(i), 
infoList[i].filePath());//保存歌曲列表
… 
 }
 showPlayList->setCurrentRow(0);
 playListBtnState = true;
showPlayList->show();
}

14.3 Cargar y guardar canciones

Abra las canciones guardadas en la lista : escriba una función y llámela en el constructor
void Widget::loadPlayListSong()
{
 //打开用户保存的歌曲列表
 configIniRead = new QSettings("PlayList.ini", QSettings::IniFormat);
QIcon musicMap(QPixmap(":/music/resource/player/playerlist/音符 1.png"));
 for(int i=0; ; ++i) //将所有的播放列表显示在列表控件中
 {
//100 是写进的值,所以返回的值也是 100
 if(configIniRead->value("/song/"+QString::number(i),100).toInt()!=100)
 {
 QString path =
configIniRead->value("/song/"+QString::number(i)).toString();
 //媒体播放内容列表需要带路径的文件名
 playListString << path;
 QFileInfo fileInfo;
 fileInfo = QFileInfo(path);
 // QString fileName = fileInfo.fileName();//文件名带后缀
 QString fileName = fileInfo.baseName();//文件名不带后缀
 // QString fileSuffix = fileInfo.suffix();//文件后缀
 //显示给用户的列表只需要显示文件名,并在显示列表前面加图标
 QListWidgetItem *songNameList = new
QListWidgetItem(musicMap,fileName);
 songNameList->setSizeHint(QSize(400,40));
 showPlayList->addItem(songNameList);
 }
 else
 {
 break;
 }
 }
 showPlayList->setCurrentRow(0);
}

15. Eliminar canciones

void Widget::deleteSongBtnSlots()
{
 configIniDelete = new QSettings("PlayList.ini",QSettings::IniFormat);//打开播放
列表配置文件
 int currentRow = showPlayList->currentRow();
 if( currentRow >= 0)
 {
 for (int i=currentRow; ; i++) //删除配置文件的内容
 {
 if(configIniDelete->value("/song/"+QString::number(i+1),100).toInt() !=
100) //如果下一行存在播放文件
 {
 
configIniDelete->setValue("/song/"+QString::number(i),configIniDelete->value("/song
/"+QString::number(i+1)).toString());
}
 else
 {
 configIniDelete->remove("/song/"+QString::number(i));
 break;
 }
 }
 QListWidgetItem* item = showPlayList->takeItem(currentRow); //删除显示列表的
内容
 delete item;
 showPlayList->update(); //更新显示
 playListString.removeAt(currentRow); //删除播放列表的内容
}
}

¡Finalizar! ! !

Supongo que te gusta

Origin blog.csdn.net/Lushengshi/article/details/130859421
Recomendado
Clasificación