SDUc++课结课大作业:基于qt类库c++实现简单的音乐播放器

2023-11-11

2021年11月的项目,版本一,功能简单,UI界面难看,代码架构拉跨,没有核心内容,技术含量低


2022年6月21日准备重构一下代码,让架构清晰一点,加点多线程和网络通信的内容,然后这次打算在visual studio下开发了

因为之前把那些库给删掉了,需要再次安装,配置环境,然后我发现自己这篇博客太差劲了,算不上保姆级教程

就把devc++的环境配置,软件下载,系统环境配置重新写了一下
可以转到下面这篇博客
http://t.csdn.cn/DGpRf



前言

本篇博客介绍如何基于qt5制作简单音乐播放器

开发工具:devc++
实现语言:c++
需导入qt5这个库

**


以下是本篇文章正文内容

一、实现功能

  1. 拥有菜单或工具条(不要求两者都有)
  2. 播放按钮,暂停功能
  3. 通过滑动条显示进度
  4. 标签显示进度时间
  5. 可以用鼠标拖动滑块改变播放进度
  6. 可播放音频,也可以播放视频。播放音频时,标签大字显示歌曲名,播放视频时,视频名称显示在底部QStatusBar上(自行搜索用法)。
  7. 双击音频文件,可以自动打开本媒体播放器进行播放。
  8. 通过QFileDialog一次打开多个媒体文件放入QListWidget,并可以通过双击激发列表项进行播放。该功能并非硬性要求,但完成该功能的可得高分。
  9. 并且提供进度显示,还可以通过拖动进度条来变换播放位置。
  10. 上一曲,下一曲,播放模式切换。
  11. 设计具有一定实用性的媒体播放器,其中视频用QGraphicsVideoItem显示。

二、研发进度记录

环境配置

系统环境配置

qt类库下载

从以下链接下载QT类库的在线安装程序: 链接:https://pan.baidu.com/s/1mZK_3-9f23455gyxljmrkQ
提取码:2019

或者从以下网站下载在线安装文件4.1.1版本,点击执行进行安装。 Download Qt: Get Qt Online Installer
安装过程中需要注册,请按照要求注册。然后输入Email和密码进入下一步
这里是引用


devc++的软件编译配置


在DEV C++菜单中选择Tools,Compiler Options,在弹出的窗口中,点击右上方带加号的按钮(Add a blank compiler set),然后输入新编译器名字,比如MinGW810_64 Compiler,点击OK退出。在General中勾选Add the following commands when calling the compile,然后复制以下内容在方框中:-O2 -lqt5core -lqt5widgets -lqt5gui -lQt5Multimedia -lQt5MultimediaWidgets -lQt5Network -lQt5TextToSpeech -lQt5Charts -lQt5DataVisualization
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.最终效果及全部代码

在这里插入图片描述
在这里插入图片描述
代码如下
.h文件:

#ifndef LESPLAYER_H
#define LESPLAYER_H

#include <QtWidgets/QtWidgets> //包含QtWidgets头文件
#include <QtMultiMedia\QMediaPlayer>//包含播放器头文件
#include <QtMultimediaWidgets\QGraphicsVideoItem> //包含视频项头文件

class MyGraphicsView:public QGraphicsView
{
	public:
		MyGraphicsView(QWidget *parent = 0); //构造函数,参数是父窗体指针,默认是0,即没有父窗口
		QGraphicsScene *scene=new QGraphicsScene; //定义场景,用于放置视频项
		QGraphicsVideoItem *videoItem=new QGraphicsVideoItem; //定义一个视频窗口	
	private:
		void resizeEvent(QResizeEvent *event);//视图窗口尺寸改变时自动执行的函数
};

class MyMainWindow:public QMainWindow //定义一个MyMainWindow类,继承自QMainWindow窗口类
{
	public:
		MyMainWindow(QWidget *parent = 0); //构造函数,参数是父窗体指针
		QMenuBar *menuBar=new QMenuBar;//定义菜单栏对象指针menuBar
		QMediaPlayer *player=new QMediaPlayer(this); //定义一个播放器对象指针
		MyGraphicsView *view=new MyGraphicsView; //定义视图窗口,用于观看视频
		//Layout
		QHBoxLayout *hLayout = new QHBoxLayout;//存放进度条的
		QHBoxLayout *ListLayout = new QHBoxLayout;//歌曲列表list
		QHBoxLayout *buttonLayout = new QHBoxLayout;//开始、暂停、上下一首
		QHBoxLayout *name_list = new QHBoxLayout;//歌曲名-播放进度条-列表
		QVBoxLayout *verticalLayout = new QVBoxLayout;//整个的垂直结构
		QVBoxLayout *play_slider = new QVBoxLayout;
		//Slider
		QSlider *slider=new QSlider; //创建QSlider对象指针
		//ListWidget
		QWidget *centralWidget=new QWidget;//定义一个QWidget对象指针centralWidget
		QListWidget *listWidget = new QListWidget;//列表窗
		//Label
		QLabel *timeLabel = new QLabel;//显示实时的时间
		QLabel *durationLabel = new QLabel;//显示总时间
		QLabel *songName = new QLabel;//歌名标签
		//Button
		QPushButton *startButton = new QPushButton;//播放按钮
		QPushButton *nextLButton = new QPushButton;//左按钮
		QPushButton *nextRButton = new QPushButton;//右按钮
		QPushButton *importMusic = new QPushButton;//右按钮
		QPushButton *playMode =  new QPushButton;//模式切换按钮
		//标志
		int flag = 1;//播放暂停按钮播放控制
		int playNow = 0;//正在播放曲目控制
		int Mode = 1;//播放模式控制标志
		void listWidgetItemActivated(QListWidgetItem *activatedItem); //item列表项被激发以后的处理函数
		void openFile(); //点击open菜单项时的处理函数
		void openMusic();//打开音乐
		void videoPositionChanged(double position);//进度变化
		void durationChanged(double duration);//获取总时间
		void mediaStatusChanged(QMediaPlayer::MediaStatus statu); //让歌曲进度随进度条变化而改变
		void sliderMovedEvent();//
		void sliderReleasedEvent();
		void sliderPressedEvent();
		void startButtonEvent();//播放
		void pauseButtonEvent();//暂停
		void stopButtonEvent();//停止
		void importLocalSongs();//导入本地音乐
		void lastMusic();//上一曲
		void nextMusic();//下一曲
		void changeList();//列表变化
		void changeMode();//播放模式改变
		void inputInformation();//错误提示
		int generateRandomNumber();
};

#endif // LESPLAYER_H

.cpp文件

#include "LesPlayer.h"
#define cn QString::fromLocal8Bit //中文字符显示
MyGraphicsView::MyGraphicsView(QWidget *parent):QGraphicsView(parent)
{
	this->setStyleSheet("background-color:rgb(232,255,255);");//通过样式表设置背景色
	this->setContentsMargins(0,0,0,0); //设定边界宽度是0
	this->setFocusPolicy(Qt::NoFocus); //设置本控件不接收焦点
	this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); //禁止水平滚动条显示
	this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);	//禁止垂直滚动条显示
	this->setMinimumSize(QSize(520,280));//设置窗口最小尺寸
	this->setScene(scene); //设置视图窗口要观看的场景为scene
	scene->addItem(videoItem); //添加视频项videoItem到场景scene
}
void MyGraphicsView::resizeEvent(QResizeEvent *event)
{
	scene->setSceneRect(0, 0, this->width(), this->height()); //设置场景scene的显示坐标范围和视图窗口相同
	videoItem->setSize(QSize(this->width(), this->height())); //设置视频项的大小和场景一致。
}
//定义构造函数,参数是父窗体指针,先调用基类构造函数QMainWindow(parent)
MyMainWindow::MyMainWindow(QWidget *parent):QMainWindow(parent)
{
	this->setWindowTitle("Libin Music"); //设置窗体的标题
	this->resize(960,600); 		//变更窗体尺寸
	this->setMenuBar(menuBar); //menuBar设置为本窗口的菜单栏
	this->setCentralWidget(centralWidget);//设置一个widget
	this->setWindowIcon(QPixmap("logoIcon.png"));//窗口图标
	//定义菜单对象指针fileMenu,显示“File”
	QMenu *fileMenu=new QMenu("File"); 
	//为fileMen添加一个菜单项,有图标和点击时的处理函数openFile();
	fileMenu->addAction(QPixmap("open.png"), "OpenVideo", this, &openFile); 
	fileMenu->addAction(QPixmap("open.png"), "OpenMusic", this, &openMusic); 
	menuBar->addMenu(fileMenu); //将fileMenu菜单添加到菜单栏
	//进度条管理
	slider->setRange(1,100); //设定数据范围
	slider->setSingleStep(5); //设定单次步长
	slider->setPageStep(5); //设定PageUp和PageDown步长
	slider->setFixedWidth(600); //设定控件固定宽度
	slider->setOrientation(Qt::Horizontal); //设定控件显示方位
	//下一曲按钮
	QPixmap nextRicon(tr("next.png"));
  	nextRButton->setIcon(nextRicon);
 	nextRButton->setFixedSize(nextRicon.size());
	nextRButton->setStyleSheet("background-color:rgb(20,145,168);""color:rgb(248,244,237);");
	nextRButton->setCursor(Qt::PointingHandCursor);
	//开始按钮设置
	QPixmap pauseIcon(tr("play4.png"));
    startButton->setIcon(pauseIcon);
 	startButton->setFixedSize(nextRicon.size());
	startButton->setStyleSheet("background-color:rgb(20,145,168);""color:rgb(248,244,237);");
	startButton->setCursor(Qt::PointingHandCursor);
	//上一曲按钮
	QPixmap nextLicon(tr("last.png"));
  	nextLButton->setIcon(nextLicon);
 	nextLButton->setFixedSize(nextLicon.size());
	nextLButton->setStyleSheet("background-color:rgb(20,145,168);""color:rgb(248,244,237);");
	nextLButton->setCursor(Qt::PointingHandCursor);
	//导入音乐列表
	QPixmap ListIcon(tr("menu.png"));
  	importMusic->setIcon(ListIcon);
 	importMusic->setFixedSize(80,80);
	importMusic->setStyleSheet("background-color:rgb(20,145,168);""color:rgb(20,145,168);");
	importMusic->setCursor(Qt::PointingHandCursor);
	QString str=QString(cn("导入本地音乐\n"));
	importMusic->setToolTip(str);
	//模式切换按钮
	playMode->setIcon(QPixmap("Sequential.png"));
	playMode->setFixedSize(nextLicon.size());
	playMode->setStyleSheet("background-color:rgb(20,145,168);""color:rgb(20,145,168);");
	playMode->setCursor(Qt::PointingHandCursor);
	//歌曲名label
	songName->setMinimumSize(120,80);
	songName->setMaximumSize(120,80);//固定大小,防止乱跑
	songName->setText(cn("音乐的力量"));
	songName->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
	songName->setStyleSheet("background-color:rgb(20,145,168);""color:rgb(248,244,237);");
	songName->setWordWrap(true);//Label内容换行
	//进度时间层
	hLayout->addWidget(timeLabel);
	hLayout->addWidget(slider);
	hLayout->addWidget(durationLabel);
	//按钮层添加按钮
	buttonLayout->addWidget(playMode);//播放模式
	buttonLayout->addWidget(nextLButton);
	buttonLayout->addWidget(startButton);
	buttonLayout->addWidget(nextRButton);
	//play_slider 上播放按钮,下进度条
	play_slider->addLayout(buttonLayout);
	play_slider->addLayout(hLayout);
	//name_list歌曲名-播放进度条-列表
	name_list->addWidget(songName);
	name_list->addLayout(play_slider);
	name_list->addWidget(importMusic);
	//列表窗
	ListLayout->addWidget(listWidget);
	//垂直结构添加
	verticalLayout->addLayout(ListLayout);
	verticalLayout->addLayout(name_list);
	//添加垂直结构
	centralWidget->setLayout(verticalLayout);
	//播放器进度改变信号以及该信号的处理函数
	connect(player, &QMediaPlayer::positionChanged, this, &videoPositionChanged);
	//打开媒体文件时,player播放器会发出媒体总长度改变信号,用此信号设置滑动条最大值
	connect(player, &QMediaPlayer::durationChanged, this, &durationChanged);
	//播放器的媒体状态改变信号以及该信号处理函数
	connect(player, &QMediaPlayer::mediaStatusChanged, this, &mediaStatusChanged);
	//进度条和媒体播放链接起来
	connect(slider, &QSlider::sliderMoved, this, &sliderMovedEvent);
	//检测释放进度条
	connect(slider, &QSlider::sliderReleased, this, &sliderReleasedEvent);
	//检测按压进度条
	connect(slider, &QSlider::sliderPressed, this, &sliderPressedEvent);
	//播放、暂停按钮
	connect(startButton,&QPushButton::clicked, this, &startButtonEvent);
	//下一曲
	connect(nextRButton,&QPushButton::clicked, this, &nextMusic);
	//上一曲
	connect(nextLButton,&QPushButton::clicked, this, &lastMusic);
	//建立itemActivated列表项激发信号和信号处理函数之间的连接
	connect(listWidget, &QListWidget::itemActivated, this, &listWidgetItemActivated);
	//导入音乐
	connect(importMusic,&QPushButton::clicked, this, &importLocalSongs);
	//播放模式
	connect(playMode,&QPushButton::clicked, this, &changeMode);
}
//列表同步变化
void MyMainWindow::changeList(){
	for (int i=0; i<listWidget->count(); i++)//遍历列表框的所有项,设置背景色和前景色,更改图标
	{
		listWidget->item(i)->setForeground(QColor(0, 0, 0));
		listWidget->item(i)->setBackground(QColor(255, 255, 255));	
		listWidget->item(i)->setIcon(QPixmap("MultiMedia 32p-3.ico"));
	}
	listWidget->item(playNow)->setForeground(QColor(255, 0, 0)); 
	listWidget->item(playNow)->setBackground(QColor(0, 255, 0));
	listWidget->item(playNow)->setIcon(QPixmap("play2.png"));
	//下面是列表显示的同步设置
	QString musicFullName = listWidget->item(playNow)->data(Qt::UserRole).toString(); 
	QFileInfo fileInfo(musicFullName); //创建文件信息类对象fileInfo
	QString fileName=fileInfo.fileName(); //从fileInfo中获得文件名(无路径)
	songName->setText(fileName);
	//开始按钮同步
    startButton->setIcon(QPixmap("play2.png"));
	flag = 1;
}
//滑动条最大值
void MyMainWindow::durationChanged(double duration) 
{
	slider->setMaximum(duration); //设置滑动条最大值
	int min = duration/1000/60;//分钟
	int s = (duration/1000/60 - min)*60;//秒数
	QString durationText = QString::number(min)+":"+QString::number(s);//durationlabel显示内容
	durationLabel->setMinimumSize(80,60);
	durationLabel->setMaximumSize(80,60);//固定大小,防止乱跑
	durationLabel->setText(durationText); //媒体总长度(分钟)
	durationLabel->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
	durationLabel->setStyleSheet("background-color:rgb(248,244,237);""color:rgb(20,145,168);");
	durationLabel->setWordWrap(true);//Label内容换行
}
//进度条实时变化
void MyMainWindow::videoPositionChanged(double position) //播放器进度信号的处理函数
{
	slider->setValue(position); //播放器进度改变时,更改滑动条上滑块的位置显示进度。
	int min = position/1000/60;//分钟
	int s = (position/1000/60 - min)*60;//秒数
	QString positionText = QString::number(min)+":"+QString::number(s);//进度label显示内容
	if(min == 0){
		positionText = QString::number(s);
	}
	timeLabel->setMinimumSize(80,60);
	timeLabel->setMaximumSize(80,60);//固定大小,防止乱跑
	timeLabel->setText(positionText); //当前播放进度
	timeLabel->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
	timeLabel->setStyleSheet("background-color:rgb(248,244,237);""color:rgb(20,145,168);");
	timeLabel->setWordWrap(true);//Label内容换行
}
//导入本地音乐
void MyMainWindow:: importLocalSongs(){
	QStringList filenames=QFileDialog::getOpenFileNames(this, "Open File", "","Music(*.mp3 *.flac *.ape);;All files (*.*)");
	for (int i=0; i<filenames.count(); i++){
		QFileInfo fileInfo(filenames.at(i));
		QString fileName = fileInfo.fileName();
		QListWidgetItem *item=new QListWidgetItem; //定义列表项
		item->setIcon(QPixmap("MultiMedia 32p-3.ico")); //设置列表项图标
		item->setText(fileName);//设置显示文本,比如显示歌名
		item->setData(Qt::UserRole, filenames.at(i));
		listWidget->addItem(item);//添加列表项到列表框
	}
	hLayout->addWidget(slider);
}
//歌曲列表双击操作
void MyMainWindow::listWidgetItemActivated(QListWidgetItem *activatedItem)
{
	for (int i=0; i<listWidget->count(); i++)//遍历列表框的所有项,设置背景色和前景色,更改图标
	{
		listWidget->item(i)->setForeground(QColor(0, 0, 0));
		listWidget->item(i)->setBackground(QColor(255, 255, 255));	
		listWidget->item(i)->setIcon(QPixmap("MultiMedia 32p-3.ico"));
	}
	playNow = listWidget->currentRow();
	activatedItem->setForeground(QColor(255, 0, 0)); 
	activatedItem->setBackground(QColor(0, 255, 0));
	activatedItem->setIcon(QPixmap("play2.png"));
	QString musicFullName = activatedItem->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
	player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
	player->play();//开始播放
	QFileInfo fileInfo(musicFullName); //创建文件信息类对象fileInfo
	QString fileName=fileInfo.fileName(); //从fileInfo中获得文件名(无路径)
	songName->setText(fileName);
	QPixmap startIcon(tr("play2.png"));
    startButton->setIcon(startIcon);
	flag = 1;
	hLayout->addWidget(timeLabel);
	hLayout->addWidget(slider);
	hLayout->addWidget(durationLabel);
}
//打开音乐
void MyMainWindow:: openMusic()
{
	//打开文件选择对话框,过滤器选择mp3,flac,ape音乐文件,或者所有文件。
	QString fileFullName = QFileDialog::getOpenFileName(this, "Open Music", "","Music(*.mp3 *.flac *.ape);;All files (*.*)");
	if (fileFullName=="") return;//如果没有选择,返回。
	player->setMedia(QUrl::fromLocalFile(fileFullName));//设置播放器的媒体文件
	QPixmap startIcon(tr("play2.png"));
	startButton->setIcon(startIcon);//按钮设置成开始的样子
	player->play();//开始播放
	
	QFileInfo fileInfo(fileFullName); //创建文件信息类对象fileInfo
	QString fileName=fileInfo.fileName(); //从fileInfo中获得文件名(无路径)
	for (int i=0; i<listWidget->count(); i++)//遍历列表框的所有项,设置背景色和前景色,更改图标
	{
		listWidget->item(i)->setForeground(QColor(0, 0, 0));
		listWidget->item(i)->setBackground(QColor(255, 255, 255));	
		listWidget->item(i)->setIcon(QPixmap("MultiMedia 32p-3.ico"));
	}
	QListWidgetItem *item=new QListWidgetItem; //定义列表项
	item->setForeground(QColor(255, 0, 0)); 
	item->setBackground(QColor(0, 255, 0));
	item->setIcon(QPixmap("play2.png"));
	item->setText(fileName);//设置显示文本,比如显示歌名
	item->setData(Qt::UserRole, fileFullName);
	listWidget->addItem(item);//添加列表项到列表框
	songName->setText(fileName);
	playNow = listWidget->count() - 1;
}
//上一曲
void MyMainWindow:: lastMusic(){
	//上一曲,首位置,转回最后,其他的减减
	if(playNow == 0){
		playNow =listWidget->count()-1;
	}
	else{
		playNow--;
	}
	QString musicFullName = listWidget->item(playNow)->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
	player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
	player->play();//开始播放
	//列表显示同步
	changeList();//调用changeList函数
}

//下一曲
void MyMainWindow:: nextMusic(){
	//下一曲1.末尾,转回第一曲2.不是末尾,加加
	if(playNow == listWidget->count()-1){
		playNow = 0;
	}
	else{
		playNow++;
	}
	QString musicFullName = listWidget->item(playNow)->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
	player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
	player->play();//开始播放
	//列表显示同步
	changeList();//调用changeList函数
}
//播放模式改变,仅改变值,播放让状态函数变化
void MyMainWindow::changeMode(){

		if (Mode == 1)
		{
			Mode++;
			playMode->setIcon(QPixmap("Loop.png"));
		}
		else if(Mode == 2)
		{
			Mode++;
			playMode->setIcon(QPixmap("Random.png"));
		}
		else{
			Mode = 1;
			playMode->setIcon(QPixmap("Sequential.png"));
		}
}
//提示信息
void MyMainWindow::inputInformation()
{
	
}
//利用自带的函数来做1.顺序直接用nextMusic,2.循环不改变playNow3.随机,palyNow取1-list.count的随机数
void MyMainWindow:: mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
	if (status == QMediaPlayer::InvalidMedia)   //无法播放媒体文件,输出错误信息
	{
		inputInformation();
	}
	else if (status == QMediaPlayer::EndOfMedia) //当前文件播放结束,播放下一首?
	{
		if (Mode == 1){
			nextMusic();
		}
		else if(Mode == 2){
			QString musicFullName = listWidget->item(playNow)->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
			player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
			player->play();//开始播放
			//列表显示同步
			changeList();//调用changeList函数
		}
		else{
			playNow = generateRandomNumber();
			QString musicFullName = listWidget->item(playNow)->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
			player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
			player->play();//开始播放
			//列表显示同步
			changeList();//调用changeList函数
		}
	}
}
//随机数产生
int MyMainWindow:: generateRandomNumber()
{
	int playRandom;
    QRandomGenerator(QTime(0,0,0).secsTo(QTime::currentTime()));
    do{
	playRandom =qrand()%listWidget->count();   	
	}
	while(playNow == playRandom); 	
    return playRandom;
}
void MyMainWindow::sliderPressedEvent()
{
	disconnect(player, &QMediaPlayer::positionChanged, this, &videoPositionChanged);
}
void MyMainWindow::startButtonEvent()
{
	if(flag == 0){
		player->play();//开始播放
		QPixmap startIcon(tr("play2.png"));
    	startButton->setIcon(startIcon);
		flag = 1;
	}
	else if(flag == 1){
		player->pause();//暂停播放
		QPixmap pauseIcon(tr("play4.png"));
    	startButton->setIcon(pauseIcon);
    	flag = 0;
	}
}
void MyMainWindow::sliderReleasedEvent()
{
	player->setPosition(slider->value());
	connect(player, &QMediaPlayer::positionChanged, this, &videoPositionChanged);
}

void MyMainWindow::sliderMovedEvent()
{
	timeLabel->setText(QString::number(slider->value()/1000/60)); //显示调整进度(分钟)
}

void MyMainWindow:: openFile()
{
	//打开文件选择对话框,过滤器选择mp4,mkv,avi等视频文件
	QString fileFullName = QFileDialog::getOpenFileName(this, "Open File", "","Videos(*.mp4 *.mkv *.avi *.wmv *.mov *.mpg *.rm *.rmvb);;All files (*.*)");
	if (fileFullName=="") return;//如果没有选择文件,返回。
	player->setMedia(QUrl::fromLocalFile(fileFullName));//设置播放器的媒体文件
	player->play();//开始播放
	view->fitInView(view->videoItem, Qt::KeepAspectRatio); //将视频项保持纵横比缩放到和视图窗口一样大小。
}

int main(int argc, char *argv[])
{
	QApplication app(argc, argv); 
	MyMainWindow mainWindow; 
	mainWindow.show();
	mainWindow.setGeometry(40,40,1800,1000);//位置
	//程序启动时接收的参数字符串列表,中文也自动转换为Unicode格式
	QStringList args = QApplication::arguments(); 
	int argsSize = args.size();//获得列表中的字符串个数
	if (argsSize>1) //args[0]是程序名,如果字符串个数超过1,表示main函数有参数输入
	{
		mainWindow.player->setMedia(QUrl::fromLocalFile(args[1]));//将args[1]参数设置为媒体源
		mainWindow.player->play();//调用mainWindow窗口中的公用成员player播放媒体文件
		mainWindow.songName->setText(args[1]);//将args[1]设置为主窗口公用成员label的显示文本
	}
	return app.exec(); 
}

2.file按钮打开文件

QMenu *fileMenu=new QMenu("File"); 
	//为fileMen添加一个菜单项,有图标和点击时的处理函数openFile();
	fileMenu->addAction(QPixmap("open.png"), "OpenVideo", this, &openFile); 
	fileMenu->addAction(QPixmap("open.png"), "OpenMusic", this, &openMusic); 
	menuBar->addMenu(fileMenu); //将fileMenu菜单添加到菜单栏

将按钮与函数做一个connect,实际上这里打开文件管理器是通过QFileDialog::getOpenFileName实现的,而不是直接与menu联系起来的。

void MyMainWindow:: openMusic()
{
	//打开文件选择对话框,过滤器选择mp3,flac,ape音乐文件,或者所有文件。
	QString fileFullName = QFileDialog::getOpenFileName(this, "Open Music", "","Music(*.mp3 *.flac *.ape);;All files (*.*)");
	

3. listWidget详解

listWidget是一个列表窗口,实例化后是一个自成体系的组件,主要由list->item构成内部,各种操作也是通过对item的操作来进行的。
在播放器中主要
1.list图标和背景改变以达到歌曲切换的效果

	for (int i=0; i<listWidget->count(); i++)//遍历列表框的所有项,设置背景色和前景色,更改图标
	{
		listWidget->item(i)->setForeground(QColor(0, 0, 0));
		listWidget->item(i)->setBackground(QColor(255, 255, 255));	
		listWidget->item(i)->setIcon(QPixmap("MultiMedia 32p-3.ico"));
	}

先把所有的列表都都变统一

	QListWidgetItem *item=new QListWidgetItem; //定义列表项
	item->setForeground(QColor(255, 0, 0)); 
	item->setBackground(QColor(0, 255, 0));
	item->setIcon(QPixmap("play2.png"));
	item->setText(fileName);//设置显示文本,比如显示歌名
	item->setData(Qt::UserRole, fileFullName);

再把正在播放的那个变成独特的

2.list双击,这个在下面详细说

4.slider控制音乐播放进度

这个很简单,slider组件是自动检测正在播放的音频文件的,都不用你多做,系统自动带着的功能

//滑动条最大值
void MyMainWindow::durationChanged(double duration) 
{
	slider->setMaximum(duration); //设置滑动条最大值
}
//进度条实时变化
void MyMainWindow::videoPositionChanged(double position) //播放器进度信号的处理函数
{
	slider->setValue(position); //播放器进度改变时,更改滑动条上滑块的位置显示进度。
}

5.多选文件添加到listWidget中

这个也很简单,QStringList filenames=QFileDialog::getOpenFileNames(this, “Open File”, “”,"Music(.mp3 .flac .ape);;All files (.)");*
打开文件时,按ctrl键来多选文件

QStringList filenames=QFileDialog::getOpenFileNames(this, "Open File", "","Music(*.mp3 *.flac *.ape);;All files (*.*)");
	for (int i=0; i<filenames.count(); i++){
		QFileInfo fileInfo(filenames.at(i));
		QString fileName = fileInfo.fileName();
		QListWidgetItem *item=new QListWidgetItem; //定义列表项
		item->setIcon(QPixmap("MultiMedia 32p-3.ico")); //设置列表项图标
		item->setText(fileName);//设置显示文本,比如显示歌名
		item->setData(Qt::UserRole, filenames.at(i));
		listWidget->addItem(item);//添加列表项到列表框
	}

6.播放暂停按钮

非常巧妙,一个键控制播放暂停,一看就懂
就是设置一个标志变量:flag,按下暂停按钮置为0,按下开始按钮置为1,其实这里只有一个按钮,两个不同是icon设置不同而已。

//播放暂停
void MyMainWindow::startButtonEvent()
{
	if(flag == 0){
		player->play();//开始播放
		QPixmap startIcon(tr("play2.png"));
    	startButton->setIcon(startIcon);
		flag = 1;
	}
	else if(flag == 1){
		player->pause();//暂停播放
		QPixmap pauseIcon(tr("play4.png"));
    	startButton->setIcon(pauseIcon);
    	flag = 0;
	}
}

7.进度显示,怎么转换成 分:秒的形式

也很简单,slider默认的是内存字节大小,先除以1000,换成60进制的。
QString::number(),数字转字符串

//滑动条最大值
void MyMainWindow::durationChanged(double duration) 
{
	slider->setMaximum(duration); //设置滑动条最大值
	int min = duration/1000/60;//分钟
	int s = (duration/1000/60 - min)*60;//秒数
	QString durationText = QString::number(min)+":"+QString::number(s);//durationlabel显示内容
	durationLabel->setText(durationText); //媒体总长度(分钟)
	durationLabel->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
	durationLabel->setStyleSheet("background-color:rgb(248,244,237);""color:rgb(20,145,168);");
	durationLabel->setWordWrap(true);//Label内容换行
}
//进度条实时变化
void MyMainWindow::videoPositionChanged(double position) //播放器进度信号的处理函数
{
	slider->setValue(position); //播放器进度改变时,更改滑动条上滑块的位置显示进度。
	int min = position/1000/60;//分钟
	int s = (position/1000/60 - min)*60;//秒数
	QString positionText = QString::number(min)+":"+QString::number(s);//进度label显示内容
	if(min == 0){
		positionText = QString::number(s);
	}
	timeLabel->setText(positionText); //当前播放进度
	timeLabel->setAlignment(Qt::AlignCenter | Qt::AlignHCenter);
	timeLabel->setStyleSheet("background-color:rgb(248,244,237);""color:rgb(20,145,168);");
	timeLabel->setWordWrap(true);//Label内容换行
}

8.双击歌曲名播放音乐

这个利用的是listWidget的自动传参功能,双击传给函数一个参数:被双击的这个item,然后进行操作,怎么实现播放呢。
1.要保证几种途径添加到列表的歌曲setData要有,也就是要知道文件的地址。
2.双击后,传递item的同时,传递了item的data
3.将item的data设置成播放的源。

void MyMainWindow::listWidgetItemActivated(QListWidgetItem *activatedItem)
{
	
	QString musicFullName = activatedItem->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
	player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
	player->play();//开始播放
	QFileInfo fileInfo(musicFullName); //创建文件信息类对象fileInfo
	QString fileName=fileInfo.fileName(); //从fileInfo中获得文件名(无路径)
}

9.上一曲、下一曲

上一曲和下一曲功能的实现核心是知道现在播放的位置
因为我们这个软件播放的实现有两种情况
1.通过file这个menu打开文件播放,这种情况是添加在list末尾,所以palyNow的值是list.count().
2.双击播放,这时候playNow的值是 activateItem.At(n).
这样就好办了,上一曲和下一曲不过是将播放器的播放源设置成list(playNow+/-1).data即可
其中注意的是,首尾;两个位置需要置首或回到末尾。

10.playMode播放模式切换

这个类比播放暂停,也是一个按钮三个功能,1、2、3数字的变化对应三种下一曲的playNow的取值
其中比较麻烦的是随机模式,随机数的取法在qt下比较麻烦

 QRandomGenerator(QTime(0,0,0).secsTo(QTime::currentTime()));

实现的种子的改变,随着时间变化而变化,否则这个种子不变会产生相同的随机数
do while的好处是可以先得到一个判断值,如果先判断的话就得先确定一个值。
在这里do while,先do出来一个随机数,这样while就好添加判断条件了。
如果用while的话,不知道怎么写。

//随机数产生
int MyMainWindow:: generateRandomNumber()
{
	int playRandom;
    QRandomGenerator(QTime(0,0,0).secsTo(QTime::currentTime()));
    do{
	playRandom =qrand()%listWidget->count();   	
	}
	while(playNow == playRandom); 	
    return playRandom;
}

得到随机数随机模式也好办了

//播放模式改变,仅改变值,播放让状态函数变化
void MyMainWindow::changeMode(){

		if (Mode == 1)
		{
			Mode++;
			playMode->setIcon(QPixmap("Loop.png"));
		}
		else if(Mode == 2)
		{
			Mode++;
			playMode->setIcon(QPixmap("Random.png"));
		}
		else{
			Mode = 1;
			playMode->setIcon(QPixmap("Sequential.png"));
		}
}

前面这个函数只负责控制按钮的样子,以及给出mode编号1,2,3,他们在按钮按下时的改变关系。

//利用自带的函数来做1.顺序直接用nextMusic,2.循环不改变playNow3.随机,palyNow取1-list.count的随机数
void MyMainWindow:: mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
	if (status == QMediaPlayer::InvalidMedia)   //无法播放媒体文件,输出错误信息
	{
		inputInformation();
	}
	else if (status == QMediaPlayer::EndOfMedia) //当前文件播放结束,播放下一首?
	{
		if (Mode == 1){
			nextMusic();
		}
		else if(Mode == 2){
			QString musicFullName = listWidget->item(playNow)->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
			player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
			player->play();//开始播放
			//列表显示同步
			changeList();//调用changeList函数
		}
		else{
			playNow = generateRandomNumber();
			QString musicFullName = listWidget->item(playNow)->data(Qt::UserRole).toString(); //获得用户数据,也就是因为文件全名,可以送到播放器播放
			player->setMedia(QUrl::fromLocalFile(musicFullName));//设置播放器的媒体文件
			player->play();//开始播放
			//列表显示同步
			changeList();//调用changeList函数
		}
	}
}

这里很关键的一个:

void MyMainWindow:: mediaStatusChanged(QMediaPlayer::MediaStatus status)
{
	if (status == QMediaPlayer::InvalidMedia)   //无法播放媒体文件,输出错误信息
	{
		inputInformation();
	}
	else if (status == QMediaPlayer::EndOfMedia) //当前文件播放结束,播放下一首?
	{
	}
}

这个和slider一样,自动检测你的文件播放状态,我们的播放模式是在下一曲切换歌曲的时候起作用的,这里也是,结合这个做到播放模式变换的功能。
顺序播放:直接nextMusic函数
随机播放:把随机数传递过去,作为playNow。
循环,每次都playNow

11.main函数传参实现打开方式的选择

int main(int argc, char *argv[])
{
	QApplication app(argc, argv); 
MyMainWindow mainWindow; 
	mainWindow.show();
	mainWindow.setGeometry(40,40,1800,1000);//位置
	//程序启动时接收的参数字符串列表,中文也自动转换为Unicode格式
	QStringList args = QApplication::arguments(); 
	int argsSize = args.size();//获得列表中的字符串个数
	if (argsSize>1) //args[0]是程序名,如果字符串个数超过1,表示main函数有参数输入
	{
		mainWindow.show();
		mainWindow.setGeometry(40,40,1800,1000);//位置
		mainWindow.player->setMedia(QUrl::fromLocalFile(args[1]));//将args[1]参数设置为媒体源
		mainWindow.songName->setText(args[1]);//将args[1]设置为主窗口公用成员label的显示文本
		//打开文件选择对话框,过滤器选择mp3,flac,ape音乐文件,或者所有文件。
		mainWindow.startButton->setIcon(QPixmap ("play2.png"));//按钮设置成开始的样子
		mainWindow.player->play();//开始播放
	
		QFileInfo fileInfo(args[1]); //创建文件信息类对象fileInfo
		QString fileName=fileInfo.fileName(); //从fileInfo中获得文件名(无路径)
		for (int i=0; i<mainWindow.listWidget->count(); i++)//遍历列表框的所有项,设置背景色和前景色,更改图标
		{
			mainWindow.listWidget->item(i)->setForeground(QColor(0, 0, 0));
			mainWindow.listWidget->item(i)->setBackground(QColor(255, 255, 255));	
			mainWindow.listWidget->item(i)->setIcon(QPixmap("MultiMedia 32p-3.ico"));
		}
		QListWidgetItem *item=new QListWidgetItem; //定义列表项
		item->setForeground(QColor(255, 0, 0)); 
		item->setBackground(QColor(0, 255, 0));
		item->setIcon(QPixmap("play2.png"));
		item->setText(fileName);//设置显示文本,比如显示歌名
		item->setData(Qt::UserRole, QUrl::fromLocalFile(args[1]));
		mainWindow.listWidget->addItem(item);//添加列表项到列表框
		mainWindow.songName->setText(fileName);
		mainWindow.playNow = mainWindow.listWidget->count() - 1;
		}
	return app.exec(); 
}

就是打开方式应该是操作系统传一个参数args【1】过来,这个参数里是文件地址,然后在main函数里对这个文件全名处理就可以了。

细节 1. 去掉控制台

编译器选项添加指令-mwindow

细节 2. exe版本发布

qt发布exe多简单啊
CPP和EXE文件单独放一个目录下,然后打开CPP文件,在dev c++界面上点击Tools菜单,然后选择prompt command,打开一个黑方框窗口,在此窗口下输入Windeployqt LiBinMusic.exe就可以产生安装所需文件包。

细节3.LAV audio解码器

不然播放不了flac等文件,只能播放mp3
http://codecguide.com/download_kl.htm
大家到以上网站下载音视频解码器,安装过程中针对各种选项全部回车即可。


总结

本文仅仅简单介绍了简易播放器的制作,算是qt一个入门级的小项目吧。希望之后还能开发更多有趣的app
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SDUc++课结课大作业:基于qt类库c++实现简单的音乐播放器 的相关文章

  • 强制 const 存储返回的值 value

    这就是我想要实现的目标 struct test const test returnconst return test test returnnonconst return test int main test t1 returnnoncon
  • 类变量在其定义范围内?

    这可能是一个愚蠢的问题 我正在尝试制作文本泥 我需要每个 Room 类包含其他 Room 类 以便在尝试移动到它们或从它们获取信息时可以引用 但是 我不能这样做 因为我显然无法在其定义中声明一个类 那么 我该怎么做呢 当我说我做不到时 我的
  • 代码块调试问题

    我正在尝试在代码块中运行一个简单的链表程序 但我无法运行该程序并且收到以下错误 Active debugger config GDB CDB debugger Default Building to ensure sources are u
  • 任务计划程序控制台输出在哪里? (C# 控制台应用程序)

    我正在运行 C Windows 控制台应用程序 并通过任务计划程序传递几个参数 它全天运行 将其他应用程序创建的平面文件数据加载到 SQL Server 中 该程序间歇性失败 并且我有 Try Catch 逻辑 该逻辑使用 Console
  • 查找周边上的点来表示边界/形状

    我有一个简单的二维网格 其格式为myGrid x y 我正在尝试找到一种方法来找到所选网格周围的周长 这样我就有了所选网格的形状 这是我的意思的一个例子 这里的想法是找到所有相关的 角点 也就是图像周边的红点 放入一个列表中 这样我就可以从
  • C# 从整数反序列化枚举

    是否可以从 C 中的 int 反序列化枚举 例如如果我有以下课程 class Employee public string Name get set public int EmployeeTypeID get set 我可以轻松地从 XML
  • 如何使用 Regsvr32 注册 .NET COM DLL?

    我有一个使用 COM DLL 的 VB6 应用程序 该DLL是用C 编写的 在 C 项目属性中 我检查了 Register for COM interop 选项 VB6 应用程序在我的开发机器上运行良好 C 代码完全遵循以下格式 CodeP
  • 类型定义存在于两个库中

    我正在使用 NET 4 5 构建 ASP NET Web 窗体网站 错误 The type System ComponentModel DataAnnotations Schema ForeignKeyAttribute exists in
  • 使用 boost::asio 是否有一种可移植的方法来查找空闲端口号

    我目前正在尝试找出一种方法来查找空闲端口号以建立连接 最好使用 boost asio 然后 该端口号将用于侦听 只有这样我才能打开套接字 大致来说 有没有办法做到 tcp resolver query query localhost por
  • C# - 如何从 Steam 交易 API 获取图标的 URL(编码)

    以下是 API 为每个项目返回的 XML 部分
  • WPF 中可选择的 TextBlock 或带有格式化文本的 TextBox

    我遇到一种情况 我需要显示格式化文本 正常 粗体 突出显示 并且还应该是可选择的 以便用户可以复制文本 我使用了文本块 我可以使用内联内容流元素应用多种格式 但不幸的是它的文本不可选择 虽然文本框允许选择文本并复制到剪贴板 但它不允许我设置
  • DLR 返回类型

    我需要 DLR 的帮助 我正在实现 IDynamicMetaObjectProvider 和 DynamicMetaObject 但在获取预期返回类型时遇到一些问题 我在元对象中覆盖 BindInvokeMember 我可以看到所有参数类型
  • 在 C# 中给定周数和年份,计算一周的开始和结束日期(基于 ISO 规范)

    我需要生成一份报告 显示一年中的 52 周 或某些年份的 53 周 及其开始日期和结束日期 有一个 ISO 规范可以做到这一点 但看起来非常复杂 我希望有人知道在 C 或 Visual Basic 中执行此操作的方法 实际上适用于 Visu
  • 创建 PING 程序时限制 ICMP 回显答复

    我正在编写一个多线程 ping 程序 我在每个线程 针对每个 IP 上创建了原始套接字 并使用 sendto 向每个线程发送了 ICMP Echo 请求 然后在每个线程中执行了 receivevfrom 我正在从各种套接字中的 IP 获取消
  • 我使用 tm/mktime 是否错误,如果没有,有解决方法吗?

    我认为下面的程序应该输出从公元 1 年到 1970 年每年第一天到 1970 年的秒数 前面是time t在编译它的系统上 CHAR BIT是一个宏 所以我认为你不能只是复制编译后的可执行文件并假设它是正确的 尽管实际上一切都使用 8 位c
  • 允许使用 AutoMapper 或类似工具映射动态类型吗?

    我已经开始使用https github com robconery massive https github com robconery massive对于一个项目 我想知道是否有任何映射工具可以支持动态到静态类型的映射 我以前使用过 Au
  • 为什么 istream/ostream 慢

    于 50 40http channel9 msdn com Events GoingNative 2013 Writing Quick Code in Cpp Quickly http channel9 msdn com Events Go
  • 为 winforms ComboBox 中的单个项目着色?

    我遇到了一个困境 我有一个表单 其中包含许多组合框 其中包含在某些情况下可能无效 过时的信息 选项 项目 我不能简单地从项目中删除过时的信息 但我确实想在选项无效时为用户提供视觉线索 我正在考虑对项目进行着色 可能是红色 来指示它们是否无效
  • 绑定未正确更新用户控件属性 MVVM

    编辑 删除旧代码 我将它放在 MainWindow xaml 上
  • 将 Web 场迁移到 ASP.NET 运行时版本 4,同时保持会话

    我们已将 Web 应用程序从 net 运行时 2 v 3 5 迁移到 net 运行时 4 v 4 5 我有一个部署问题 我们的 sessionstate 服务器是一个 stateserver 并在单独的服务器上运行框架 2 中的 aspne

随机推荐

  • JavaScript 全局

    解释 JavaScript 全局属性和方法可用于创建Javascript对象 JavaScript 全局属性 属性 描述 Infinity 代表正的无穷大的数值 NaN 指示某个值是不是数字值 undefined 指示未定义的值 JavaS
  • 宝塔面板解决跨域

    1 找到宝塔面板配置nginx文件的地方 2 增加如下代码 add header Access Control Allow Origin add header Access Control Allow Methods POST PUT GE
  • 使用git查看修改记录

    查看文件中每行代码的最近一次修改人 git blame file name git blame
  • 判断能否被3,5,7整除

    输入一个整数 判断它能否被3 5 7整除 并输出以下信息 1 能同时被3 5 7整除 直接输出3 5 7 每个数中间一个空格 2 能被其中两个数整除 输出两个数 小的在前 大的在后 例如 3 5或者 3 7或者5 7 中间用空格分隔 3 能
  • 简单的Arima模型自动最优拟合与预测

    昨天用R折腾了一个简单的时间序列数据Arima自动拟合与预测 过程不复杂 但由于用得不多 为了防止忘记 撰文记录 打开R 安装一个叫做 Forecast 的包 每次开启R后 使用之前用 library forecast 加载该包 这里我用传
  • pickle.load,pickle.dump构建Coco数据集labels的pickle文件

    1 效果图 write pickle coco classes pickle done loading coco classes pickle person bicycle car motorcycle airplane bus train
  • OSI七层模型,报文数据包帧详解,tcp三次握手与四次挥手说明,WireShark抓包分析

    目录 浅谈OSI参考模型 七层模型 什么是OSI参考模型 OSI参考模型的划分 OSI模型与TCP IP模型的比较 七层详解 工作流程 TCP IP协议栈 简介 通用协议栈描述 报文 数据报 报文段 数据包 帧的概念 tcp三次握手与四次挥
  • Callable接口详解

    Callable接口详解 Callable 返回结果并且可能抛出异常的任务 优点 可以获得任务执行返回值 通过与Future的结合 可以实现利用Future来跟踪异步计算的结果 Runnable和Callable的区别 1 Callable
  • pg_dump实例详解

    本文转自 http blog chinaunix net uid 354915 id 3504632 html 一 pg dump的用法 数据库的导入导出是最常用的功能之一 每种数据库都提供有这方面的工具 例如Oracle的exp imp
  • 密封类(sealed class)

    密封类 使用关键字 sealed 密封类里面可以有若干个子类 这些子类如果要继承密封类 则必须和密封类在同一个文件里 sealed class LicenseStatus2 单例继承密封类 object UnQualified Licens
  • 转-如何绘制业务流程图(二)

    转自 http blog jobbole com 22509 本来写完上篇 我发现没有太多必要单纯讨论这一部分内容 因为对于很多人来讲 缺的不是具体的做法 而是做这件事情的意义以及目标性的明确 一旦对这件事情的意义和目标有深刻认同 那自然会
  • JavaScript 扁平化数组转成Tree

    有时候我们得到的数据结构并不是想要的 这个时候就需要对得到的数据进行处理了 比如 我们拿到的是扁平化的数组 但我们要应用在 tree 树形组件或级联选择器组件中 这样的组件要求数据结构是具有层级递进关系的 tree 结构 或者我们并不需要层
  • 【JVM类加载及字节码技术】类加载阶段——加载、链接(一)

    类在JVM中的流程分析 类加载 1 加载 2 链接 2 1 验证 2 2 准备 2 3 解析 总结 类加载 类的生命周期 加载 gt 验证 gt 准备 gt 解析 gt 初始化 gt 使用 gt 卸载 加载阶段 加载 链接阶段 验证 准备
  • DTCC2023第十四届中国数据库大会分享:MySQL性能诊断平台:利用eBPF技术实现高效的根因诊断

    主题 8月16 18日 DTCC2023第十四届中国数据库大会在北京国际会议中心召开 17日下午在云原生数据库开发与实践分论坛 我将带来分享 MySQL性能诊断平台 利用eBPF技术实现高效的根因诊断 敬请期待 欢迎大家提前试用我们发布的产
  • 5种CSS3鼠标悬停图片显示文字信息

    下载地址 5种CSS3鼠标悬停图片显示文字信息是一款鼠标悬停特效 含5种不同风格的鼠标悬停图片显示文字信息 dd
  • 用Double-DQN方法解决简单迷宫寻路问题

    环境描述 25 25离散的栅格图 起点左上角 终点右下角 障碍物1 1随机分布 动作空间维度2 向右 向下 每次移动奖励 1 遇到障碍物或移动出环境奖励 100 到终点奖励20 注 针对这个任务期望SARSA Q learning等方法能够
  • Android中控件AutoCompleteTextView的使用方法和一些属性

    版权声明 本文为博主原创文章 未经博主允许不得转载 AutoCompleteTextView一些属性
  • “数据压缩实验之LZW 编解码算法实现与分析”实验报告_201810413045_陈诚

    文章目录 1 实验项目名称 2 实验目的 3 什么是LZW编解码算法与它的原理 3 1 LZW编解码算法介绍 3 2 LZW编解码算法原理 3 2 1 编码流程图及为了便于理解和期末复习举实例说明 3 2 2 解码流程图及举实例说明 重点说
  • 并发无锁队列学习之一

    Anker 工作学习笔记 关注云计算 网络安全 软件定义网络 博客园 新随笔 管理 随笔 169 文章 2 评论 403 并发无锁队列学习之一 开篇 1 前言 队列在计算机中非常重要的一种数据结构 尤其在操作系统中 队列典型的特征是先进先出
  • SDUc++课结课大作业:基于qt类库c++实现简单的音乐播放器

    2021年11月的项目 版本一 功能简单 UI界面难看 代码架构拉跨 没有核心内容 技术含量低 2022年6月21日准备重构一下代码 让架构清晰一点 加点多线程和网络通信的内容 然后这次打算在visual studio下开发了 因为之前把那