vs2013+Qt的学习小程序:点歌软件

勇哥学习了十来天的QT,边学边写了个小练习。放上来做为一些知识点的备查。

这个小程序的功能有:

  • 磁盘读取歌曲名列表

  • 双击歌曲名调用外部播放器播放

  • 可以支持首拼方法模糊搜索歌曲

  • 控件的右键菜单


image.png

功能很简单,但是用到了一些常用的Qt知识点,包括:


  • QListWidget控件

  • QTabWidget控件

  • QPushButton控件

  • QLineEdit控件

  • 控件相关的信号与槽

  • SIGNAL和SLOT宏

  • foreach

  • try...catch...

  • QSettings类

  • QFile类

  • QTextStream类

  • QCoreApplication类

  • QString类

  • QStringList类

  • QProcess类

  • tuple

  • qDebug

  • QMap

  • QMenu

  • QAction

  • vistual assist插件

  • Qt Designer


下面是一些知识点相关的贴子:


磁盘文件操作

QT 对文件的操作(创建、拷贝、写入、删除)  


控件右键菜单

QT实现右键快捷菜单 

Qt之给控件添加右键菜单  


汉字转拼音

Qt汉字转拼音  


启动外部程序

Qt QProcess启动和关闭外部程序  


异常处理

C++中catch(…)如何使用  

try{} catch(…){} 的问题 

C++异常处理  

C++&Qt的异常处理  


配置文件读写

QSettings读写注冊表、配置文件   



下面贴上业务逻辑的主要代码:

work.h

#pragma once
#pragma execution_character_set("utf-8")

#include <QSettings>
#include "Config.h"
#include <tuple>  

class Work 
{
public:
	//歌曲列表类型
	static enum MusicListTypeEnum
	{
		allMusic,
		selMusic,
		//搜索结果列表,用于全部歌曲标签
		searchMusicAll,
		//搜索结果列表,用于选中的歌曲标签
		searchMusicSel
	};

private:
	//全部歌曲的音乐列表,<歌曲名,歌曲文件名路径串>
	QMap<QString, QString> musicListAll;
	//选中歌曲的音乐列表,<歌曲名,歌曲文件名路径串>
	QMap<QString, QString> musicListSelect;
	//全部歌曲名称的拼音字典
	QMap<QString, QString> musicAllPyList;
	//选择歌曲名称的拼音字典
	QMap<QString, QString> musicSelPyList;
	Config* config;

private:
	//更新歌曲的拼音(全部的歌曲)
	void updateMusicAllPy();
	//更新歌曲的拼音(选中的歌曲)
	void updateMusicSelPy();
	

public:
	Work(Config* config);
	~Work();
	//读取音乐列表
	void readMusicList(Work::MusicListTypeEnum musictype);
	//按歌曲名或者简拼搜索歌曲
	QMap<QString, QString> searchMuslicList(QString name, Work::MusicListTypeEnum musictype);
	//取歌曲列表(枚举:allMusic,selMusic)
	QMap<QString, QString> getMusicList(Work::MusicListTypeEnum musictype);
	//添加歌曲到选中的歌单
	void addMusic(std::tuple<QString, QString > data);
	//删除选中歌单的歌(不能删除全部歌单中的歌)
	void delMusic(QString musicName);
	//取歌曲名拼音列表(全部歌曲)
	QMap<QString, QString> getMusicAllPyList();
	//取歌曲名拼音列表(选中的歌曲)
	QMap<QString, QString> getMusicSelPyList();
	//删除缓存的歌曲列表
	void delMusicListFile(Work::MusicListTypeEnum musictype);
};

work.cpp

#include "Work.h"
#include "CdiskFile.h"
#include "Cchineseletterhelper.h"

Work::Work(Config* config)
{
	this->config = config;
}

Work::~Work()
{
}

void Work::readMusicList(Work::MusicListTypeEnum musictype)
{
	QString  allmusicPath = config->get("mtvconfig", "allMusic").toString();
	QString selmusicPath = config->get("mtvconfig", "selMusic").toString();
	QString mtvPath = config->get("mtvconfig", "mtvDir").toString();

	if (musictype == Work::MusicListTypeEnum::selMusic){
		QString txt = CdiskFile::readAllTxt(selmusicPath);
		if (musicListSelect.count() < 2){
			QFile f1;
			if (f1.exists(selmusicPath)){
				//如果selMusic.txt存在由磁盘缓存文件重建内存表
				musicListSelect = CdiskFile::QMapLoad(selmusicPath);
			}
			f1.close();
			updateMusicSelPy();
		}
		return;
	}
	else{
		try
		{
			QString txt = CdiskFile::readAllTxt(allmusicPath);
			if (musicListAll.count() < 2){
				QFile f1;
				if (f1.exists(allmusicPath)){
					//如果allMusic.txt存在由磁盘缓存文件重建内存表
					musicListAll = CdiskFile::QMapLoad(allmusicPath);
					
				}
				else{
					//如果allMusic.txt不存在则读磁盘文件名重建内存表
					QStringList list1 = CdiskFile::getFileNames(mtvPath, QStringList() << "*.mkv");
					foreach(QString m, list1){
						musicListAll.insert(m, mtvPath + "/" + m);
					}
				}
				updateMusicAllPy();
				CdiskFile::QMapSave(allmusicPath, musicListAll);
			}
			return;
		}
		catch (...)
		{

		}
	}
	
}

QMap<QString, QString> Work::searchMuslicList(QString name, Work::MusicListTypeEnum musictype)
{
	QMap<QString, QString> map;
	if (musictype ==  Work::MusicListTypeEnum::allMusic){
	   auto v= musicListAll.find(name);
	   if (v != musicListAll.end()){
		   map.insert(v.key(), v.value());
	   }   
	}
	else{
		auto v = musicListSelect.find(name);
		if (v != musicListSelect.end()){
			map.insert(v.key(), v.value());
		}
	}
	return map;
}



QMap<QString, QString> Work::getMusicList(Work::MusicListTypeEnum musictype)
{
	if (musictype == Work::MusicListTypeEnum::allMusic){
		return musicListAll;
	}
	else{
		return musicListSelect;
	}
}

void Work::addMusic(std::tuple<QString ,QString > data)
{
	QString selmusicPath = config->get("mtvconfig", "selMusic").toString();
	if (!musicListSelect.contains(std::get<0>(data))){
		musicListSelect.insert(std::get<0>(data), std::get<1>(data));
		CdiskFile::QMapSave(selmusicPath, musicListSelect);
	}
}

void Work::delMusic(QString musicName)
{
	QString selmusicPath = config->get("mtvconfig", "selMusic").toString();
	if (musicListSelect.contains(musicName)){
		musicListSelect.remove(musicName);
		CdiskFile::QMapSave(selmusicPath, musicListSelect);
	}
		
}

void Work::updateMusicAllPy()
{
	foreach(QString m, musicListAll.keys()){
		musicAllPyList.insert(m, Cchineseletterhelper::GetFirstLetters(m));
	}
}

void Work::updateMusicSelPy()
{
	foreach(QString m, musicListSelect.keys()){
		musicSelPyList.insert(m, Cchineseletterhelper::GetFirstLetters(m));
	}
}

QMap<QString, QString> Work::getMusicAllPyList(){
	return musicAllPyList;
}

QMap<QString, QString> Work::getMusicSelPyList(){
	return musicSelPyList;
}

void Work::delMusicListFile(MusicListTypeEnum musictype)
{
	QFile file;
	auto fname1 = config->get("mtvconfig", "allMusic").toString();
	auto fname2 = config->get("mtvconfig", "selMusic").toString();
	try
	{
		if (musictype == Work::MusicListTypeEnum::allMusic){
			if (file.exists(fname1)){
				QFile::remove(fname1);
			}
		}
		else{
			if (file.exists(fname2)){
				QFile::remove(fname2);
			}
		}
	}
	catch (...)
	{
		
	}
	
}

QtForOpencv.h

#pragma once
#pragma execution_character_set("utf-8")
#include <QtWidgets/QWidget>
#include "ui_QtForOpencv.h"
#include <QLabel>
#include <QCoreApplication>
#include <QSettings>
#include "Config.h"
#include "Work.h"
#include "CdiskFile.h"
#include "CcsvHelper.h"
#include <QTabWidget>
#include <QListWidget>
#include <QMenu>

class QtForOpencv : public QWidget
{
	Q_OBJECT

public:
	QtForOpencv(QWidget *parent = Q_NULLPTR);
	~QtForOpencv();

private:
	Ui::QtForOpencvClass ui;

	Config* config;
	Work* work;
	QMenu * allMusicMenu;
	QMenu * selMusicMenu;
	QAction * updateMusicAction;
	QAction * addMusicAction;
	QAction * delMusicAction;

	//更新音乐列表
	void updateMusicList(QMap<QString,QString> data, Work::MusicListTypeEnum type);
	//注册UI信号与槽
	void ConnectUiEvent();
	

private slots:
	void OnBtnUpdateMusic();
	void OnBtnAddSelMusic();
	void OnBtnDelMusic();
	void OnLineEditSearchMusic(const QString data);
	void OnTabChange(int index);
	void OnListwAllMusic(QListWidgetItem * item1);

	void OnAllMusicListClick(QListWidgetItem*);
	void OnAllMusicListPlay(QListWidgetItem*);
	void OnSelMusicListClick(QListWidgetItem*);
	void OnSelMusicListPlay(QListWidgetItem*);

	void OnUpdateMenuAction(const QPoint &pos);

public:
	QLabel* imgLabel;
};

QtForOpencv.cpp

#include "QtForOpencv.h"
#include <opencv2\opencv.hpp>
#include <opencv2\core.hpp>
#include <opencv2\imgcodecs.hpp>
#include <opencv2\imgproc.hpp>
#include <QPushButton>
#include <qdebug.h>
#include <QProcess>
#include <QMessageBox>
#include "Cchineseletterhelper.h"

using namespace cv;
using namespace std;
QtForOpencv::QtForOpencv(QWidget *parent)
	: QWidget(parent)
{
	ui.setupUi(this);
	
	ConnectUiEvent();
	
	allMusicMenu = new QMenu(this);
	selMusicMenu = new QMenu(this);
	updateMusicAction = new QAction("刷新歌曲",this);
	addMusicAction = new QAction("添加到选中的歌曲", this);
	delMusicAction = new QAction("删除歌曲", this);
	allMusicMenu->addAction(updateMusicAction);
	allMusicMenu->addAction(addMusicAction);
	selMusicMenu->addAction(delMusicAction);

	connect(updateMusicAction, &QAction::triggered, [=]{
		qDebug() << "updateMusicAction";
		OnBtnUpdateMusic();
	});

	connect(addMusicAction, &QAction::triggered, [=]{
		qDebug() << "addMusicAction";
		OnBtnAddSelMusic();
	});

	connect(delMusicAction, &QAction::triggered, [=]{
		qDebug() << "delMusicAction";
		OnBtnDelMusic();
	});

	// 给控件设置上下文菜单策略
	ui.listwAllMusic->setContextMenuPolicy(Qt::CustomContextMenu);
	//鼠标右键点击控件时会发送一个void QWidget::customContextMenuRequested(const QPoint &pos)信号
	//给信号设置相应的槽函数
	//以slot函数方式connect
	connect(ui.listwAllMusic, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(OnUpdateMenuAction(const QPoint&)));
	

	//以Lambada表达式方法connect
	ui.listwSelMusic->setContextMenuPolicy(Qt::CustomContextMenu);
	connect(ui.listwSelMusic, &QListWidget::customContextMenuRequested, [=](const QPoint &pos)
	{
		qDebug() << pos;
		selMusicMenu->exec(QCursor::pos());
	});


	//初始化配置
	QString inifilePath = QCoreApplication::applicationDirPath() + "/myTest.ini";
	config = new Config(inifilePath);
	config->set("mtvconfig", "allMusic", QCoreApplication::applicationDirPath()+"/allmusic.txt");
	config->set("mtvconfig", "selMusic", QCoreApplication::applicationDirPath() + "/selmusic.txt");
	config->set("mtvconfig", "mtvDir", "e:/music");
	config->set("mtvconfig", "playerDir", "E:/Program Files/SPlayer/splayer.exe");
	//初始化工作逻辑
	work = new Work(config);
	work->readMusicList(Work::MusicListTypeEnum::allMusic);
	work->readMusicList(Work::MusicListTypeEnum::selMusic);

	ui.tabmain->setCurrentIndex(0);
	updateMusicList(work->getMusicList(Work::MusicListTypeEnum::allMusic), Work::MusicListTypeEnum::allMusic);

	auto s = sizeof(double);

}


void QtForOpencv::OnUpdateMenuAction(const QPoint &pos){
	qDebug() << pos;//参数pos用来传递右键点击时的鼠标的坐标,这个坐标一般是相对于控件左上角而言的
	allMusicMenu->exec(QCursor::pos());
}

void QtForOpencv::ConnectUiEvent()
{
	//更新歌单
	connect(ui.btnUpdateMusic, SIGNAL(clicked()), this, SLOT(OnBtnUpdateMusic()));
	//添加到选中的歌单
	connect(ui.btnAddSelMusic, SIGNAL(clicked()), this, SLOT(OnBtnAddSelMusic()));
	//删除歌曲(仅选中的歌单)
	connect(ui.btnDelMusic, &QPushButton::clicked, this, &QtForOpencv::OnBtnDelMusic);
	//歌曲搜索框内容改变
	connect(ui.lineEditSearchMusic, SIGNAL(textChanged(const QString)), this, SLOT(OnLineEditSearchMusic(const QString)));
	//tab标签被点中
	connect(ui.tabmain, SIGNAL(tabBarClicked(int)), this, SLOT(OnTabChange(int)));

	//全部歌曲列表项目被单击或双击运行
	connect(ui.listwAllMusic, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(OnAllMusicListPlay(QListWidgetItem*)));
	connect(ui.listwAllMusic, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(OnAllMusicListClick(QListWidgetItem*)));
	//选中的歌曲列表项目被单击或双击运行
	connect(ui.listwSelMusic, SIGNAL(itemDoubleClicked(QListWidgetItem*)), this, SLOT(OnSelMusicListPlay(QListWidgetItem*)));
	connect(ui.listwSelMusic, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(OnSelMusicListClick(QListWidgetItem*)));
}

void QtForOpencv::OnBtnUpdateMusic()
{
	//刷新歌曲
	qDebug() << "OnBtnUpdateMusic";
	work->delMusicListFile(Work::MusicListTypeEnum::allMusic);
	updateMusicList(work->getMusicList(Work::MusicListTypeEnum::allMusic), Work::MusicListTypeEnum::allMusic);
}

void QtForOpencv::OnBtnAddSelMusic()
{
	//添加到选中的歌曲
	qDebug() << "OnBtnAddSelMusic";
	std::tuple<QString,QString> data;
	QString musicName = ui.listwAllMusic->selectedItems()[0]->text();
	QString musicPath = config->get("mtvconfig", "mtvDir").toString() + "/" + musicName;
	data = make_tuple(musicName, musicPath);
	work->addMusic(data);
	
	updateMusicList(work->getMusicList(Work::MusicListTypeEnum::selMusic), Work::MusicListTypeEnum::selMusic);
	QMessageBox::about(NULL, "信息", "添加成功!");
}

void QtForOpencv::OnBtnDelMusic()
{
	qDebug() << "OnBtnDelMusic";
	//删除选中歌曲列表中的歌曲
	if (ui.tabmain->currentIndex() > 0){
		QString musicName = ui.listwSelMusic->selectedItems()[0]->text();
		work->delMusic(musicName);
		updateMusicList(work->getMusicList(Work::MusicListTypeEnum::selMusic), Work::MusicListTypeEnum::selMusic);
		QMessageBox::about(NULL, "信息", "已经删除!");
	}
}

void QtForOpencv::OnTabChange(int index)
{
	qDebug() << "tab..." << index ;
	switch (index)
	{
	case 0:
		ui.btnAddSelMusic->setEnabled(true);
		ui.btnUpdateMusic->setEnabled(true);
		ui.btnDelMusic->setEnabled(false);
		updateMusicList(work->getMusicList(Work::MusicListTypeEnum::allMusic), Work::MusicListTypeEnum::allMusic);
		break;
	case 1:
		ui.btnAddSelMusic->setEnabled(false);
		ui.btnUpdateMusic->setEnabled(true);
		ui.btnDelMusic->setEnabled(true);
		updateMusicList(work->getMusicList(Work::MusicListTypeEnum::selMusic), Work::MusicListTypeEnum::selMusic);
		break;
	default:
		break;
	}

}

void QtForOpencv::OnLineEditSearchMusic(const QString data)
{
	qDebug() << data;
	if (data.length() > 0){
		//QString firstLetters = Cchineseletterhelper::GetFirstLetters("");
		
		QMap<QString, QString> map1;
		if (ui.tabmain->currentIndex() == 0){
			auto list = work->getMusicAllPyList();
			auto path = config->get("mtvconfig", "mtvDir").toString();
			for (QMap<QString, QString>::iterator i = list.begin(); i != list.end(); ++i){
			 
				if (i.value().indexOf(data.toUpper()) >= 0){
					map1.insert(i.key(), path + "/" + i.key());
				}
			}
			if (map1.count() > 0){
				updateMusicList(map1, Work::MusicListTypeEnum::searchMusicAll);
			}
		}
		else if (ui.tabmain->currentIndex() == 1){
			auto list = work->getMusicSelPyList();
			auto path = config->get("mtvconfig", "mtvDir").toString();
			for (QMap<QString, QString>::iterator i = list.begin(); i != list.end(); ++i){
				if (i.value().indexOf(data.toUpper()) >= 0){
					map1.insert(i.key(), path + "/" + i.key());
				}
			}
			if (map1.count() > 0){
				updateMusicList(map1, Work::MusicListTypeEnum::searchMusicSel);
			}
		}
	}
	else{
		if (ui.tabmain->currentIndex() == 0){
			updateMusicList(work->getMusicList(Work::MusicListTypeEnum::allMusic), Work::MusicListTypeEnum::allMusic);
		}
		else if (ui.tabmain->currentIndex() == 1){
			updateMusicList(work->getMusicList(Work::MusicListTypeEnum::selMusic), Work::MusicListTypeEnum::selMusic);
		}
	}
}



void QtForOpencv::OnListwAllMusic(QListWidgetItem * item1)
{
	qDebug() << "OnListwAllMusic";
}

void QtForOpencv::updateMusicList(QMap<QString, QString> data, Work::MusicListTypeEnum type)
{
	QStringList list1;
	foreach(QString m, data.keys()){
		list1.append(m);
	}
	if (data.count() < 1) return;

	if (type == Work::MusicListTypeEnum::allMusic || type == Work::MusicListTypeEnum::searchMusicAll){
		ui.listwAllMusic->clear();
		ui.listwAllMusic->addItems(list1);
	}
	else if (type == Work::MusicListTypeEnum::selMusic || type == Work::MusicListTypeEnum::searchMusicSel){
		ui.listwSelMusic->clear();
		ui.listwSelMusic->addItems(list1);
	}

}



void QtForOpencv::OnAllMusicListClick(QListWidgetItem* item)
{
	
	//qDebug() << "OnAllMusicListClick";
}

void QtForOpencv::OnAllMusicListPlay(QListWidgetItem* item)
{
	//播放歌曲
	qDebug() << "OnAllMusicListPlay";
	
	auto mtvdir = config->get("mtvconfig", "mtvDir").toString();
	auto txt = item->text();
	auto playDir = config->get("mtvconfig", "playerDir").toString();

	auto pro = new QProcess(this);
	pro->start(playDir, QStringList(mtvdir+"/"+txt));
	pro->waitForStarted();


}

void QtForOpencv::OnSelMusicListClick(QListWidgetItem* item)
{

	//qDebug() << "OnSelMusicListClick";
}

void QtForOpencv::OnSelMusicListPlay(QListWidgetItem* item)
{

	qDebug() << "OnSelMusicListPlay";
	OnAllMusicListPlay(item);
}

QtForOpencv::~QtForOpencv()
{
	delete config;
	delete work;

}

Config.h

#pragma once
#pragma execution_character_set("utf-8")

#include <QVariant>
#include <QSettings>

class Config 
{
public:
	Config(QString filename="");
	virtual ~Config();
	//保存配置项(节点名,键名,键值)
	void set(QString, QString, QVariant);
   //读取配置项(节点名,键名)
	QVariant get(QString, QString);
private:
	QString m_qstrfilename;
	QSettings * m_psetting;
};

Config.app

#include "Config.h"
#include <QCoreApplication>
#include <QSettings>
#include <QDebug>

Config::Config(QString filename)
{
	if (filename.isEmpty())
	{
		m_qstrfilename = QCoreApplication::applicationDirPath() + "/config.ini";
	}
	else
	{
		m_qstrfilename = filename;
	}
	m_psetting = new QSettings(m_qstrfilename, QSettings::Format::IniFormat);
	qDebug() << m_qstrfilename;
}

Config::~Config()
{
	delete m_psetting;
	m_psetting = 0;
}


void Config::set(QString qstrNodeName, QString qstrKeyName, QVariant qvarValue)
{
	/* /mtvconfig/allMusic */
	m_psetting->setValue(QString("/%1/%2").arg(qstrNodeName).arg(qstrKeyName), qvarValue);
}

QVariant Config::get(QString qstrNodeName, QString qstrKeyName)
{
	QVariant qvar = m_psetting->value(QString("/%1/%2").arg(qstrNodeName).arg(qstrKeyName));
	return qvar;
}

CdiskFile.h

#pragma once
#pragma execution_character_set("utf-8")
#include <QString>
#include <QMap>
#include "CcsvHelper.h"
#include "qdir.h"
class CdiskFile
{
public:
	CdiskFile();
	virtual ~CdiskFile();
	//读取文本文件全部内容(文件名带路径)
	static QString readAllTxt(const QString filepath);
	//取指定目录下全部符合扩展名的文件名列表,递归搜索。(目录路径,扩展名列表)
	static QStringList getFileNames(const QString filepath,QStringList filters);
	//保存QMap<QString, QString>的数据到磁盘文件。(文件名路径,map数据)
	static bool QMapSave(const QString fileNamePath, QMap<QString, QString> mapdata);
	//从磁盘文件读取内容到QMap<QString, QString>。(文件名路径,文件名)
	static QMap<QString, QString> QMapLoad(const QString fileNamePath);
	//由文件名路径串拆分出文件名与目录串
	static std::tuple<QString, QString> splitFileNamePath(const QString filenamepath);
};

CdiskFile.cpp

#include "CdiskFile.h"
#include <QFile>
#include <QDir>
#include "qtextstream.h"



CdiskFile::CdiskFile()
{
}


CdiskFile::~CdiskFile()
{
}

 QString CdiskFile::readAllTxt(const QString filepath)
{
	 try
	 {
		 QFile file(filepath);
		 file.open(QIODevice::ReadOnly | QIODevice::Text);
		 QByteArray ary = file.readAll();
		 file.close();
		 return QString(ary);
	 }
	 catch (...)
	 {
		 throw;
	 }

}

 QStringList CdiskFile::getFileNames(const QString filepath, QStringList filters)
 {
	QStringList list1;
	QDir dir(filepath);
	list1 = dir.entryList(filters, QDir::Files | QDir::AllEntries, QDir::Name);
	return list1;
 }

 bool CdiskFile::QMapSave(const QString fileNamePath, QMap<QString, QString> mapdata)
 {
	 auto tup=CdiskFile::splitFileNamePath(fileNamePath);
	 QString filepath = std::get<0>(tup);
	 QString filename = std::get<1>(tup);
	 QDir dir;
	 if (!dir.exists(filepath)){
		 if (!dir.mkpath(filepath)) return false;
	 }

	 QString tmp;
	 QList<QString> list2;
	 foreach(auto m,mapdata.keys()){
		 list2.clear();
		 list2.append(m);
		 list2.append(mapdata[m]);
		
		tmp.append(CcsvHelper::createCSVRow(list2)+"\n");
	 }
	 try{
		 QFile file(filepath + "/" + filename);
		 file.open(QIODevice::WriteOnly | QIODevice::Text);
		 file.write(tmp.toUtf8());
		 file.close();
		 return true;
	 }
	 catch (...){
		 return false;
	 }
 }

 QMap<QString, QString> CdiskFile::QMapLoad(const QString fileNamePath)
 {
	 QMap<QString, QString> map;
	 auto tup = CdiskFile::splitFileNamePath(fileNamePath);
	 QString filepath = std::get<0>(tup);
	 QString filename = std::get<1>(tup);

	 QFile file(filepath + "/" + filename);
	 if (file.open(QIODevice::ReadOnly | QIODevice::Text)){
	     QTextStream in(&file);
		 in.setCodec("UTF-8");
		 auto res = in.readAll();
		 auto list1 = res.split("\n");
		 foreach(QString m, list1){
			 auto ary1 = CcsvHelper::explainCSVRow(m);
			 if (ary1.length() == 2)
				 map.insert(ary1[0], ary1[1]);
			 else
			 {
				 int k1 = 0;
			 }
		 }
	 }
	 return map;
 }

 

 std::tuple<QString, QString> CdiskFile::splitFileNamePath(const QString filenamepath)
 {
	 std::tuple<QString, QString> tup;
	 int pos1=filenamepath.lastIndexOf('/');
	 QString strPath = filenamepath.left(pos1 + 1);
	 QString strFileName = filenamepath.right(filenamepath.count() - pos1 - 1);
	 tup = std::make_tuple(strPath, strFileName);
	 return tup;
 }


image.png


这款点歌的小程序勇哥还写过其它语言版本的,放这里给各位把玩一下吧:

Python版本的:

Python Tkinter 学习成果:点歌软件music


plc+单片机+c#版本:

欧姆龙cp1h常用指令学习(十四)练习篇一:红外线遥控点歌


C#版本的:

原创C#源码,抖音热门音乐播放器


再早之前,还有一个易语言版本写的,怕被各位鄙视,还是不要放上来了吧。


这个小程序配置采用ini文件,其实相对于xml和C#的对象序列化来生成配置文件来看,是相当的原始。

而且现在也流行用PropertyGrid之类的属性流览控件来设置配置项,我想把这个程序也改造成这样的。

image.png

(属性浏览控件指的就是Qt Designer或者vs里面用到的控件属性设置面板)

等勇哥搞出来了会另起一个贴子登出来。


--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864