树形目录文件夹的遍历访问

3 篇文章 1 订阅

开发环境:Qt5.8+VS2013

1.场景:当一个文件夹里面有多个子文件夹,每个文件夹里还可以有子文件夹,最终的文件是叶子节点。当给定根节点(最顶层的文件路径时,要遍历里面的所以叶子节点(单个文件),提取其路径信息,并准备将其路径信息插入到数据库里)

用到的知识:

Qt文件目录操作:QDir类,参考http://doc.qt.io/qt-5/qdir.html 

会区别文件与目录(叶子节点与内部节点)

递归,树叶子节点的遍历

实现:FindFile()函数,递归调用,访问所有单个文件,

 


/*
FindFile()函数
输入参数:顶层文件目录路径名称QString类型
输出:再UI界面的ListWidget中列出所有的文件全路径(绝对路径)
*/
bool MainWidget::FindFile(const QString & path)
{
	QString format;
	QDir dir(path);/* Windows系统上会将Windows的文件路径上的/转换为\  */
	if (!dir.exists())
		return false;
	dir.setFilter(QDir::Dirs | QDir::Files);/*因为是用递归,所以必须有目录和文件两种过滤项*/
	dir.setSorting(QDir::DirsFirst);/*QDir::DirsFirst	0x04	Put the directories first, then the files.*/
	QFileInfoList list = dir.entryInfoList();  //获的文件夹下的所有文件列表,实际获取的多2个

	if (list.empty())
		return false;
	/*
	QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const

	Returns a list of QFileInfo objects for all the files and directories in the directory, ordered according to the name 
	
	and attribute filters previously set with setNameFilters() and setFilter(), and sorted according to the flags set with setSorting().

	The name filter, file attribute filter, and sorting specification can be overridden using the nameFilters, filters, and sort arguments.

	Returns an empty list if the directory is unreadable, does not exist, or if nothing matches the specification.

	See also entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), and exists().
*/

	int i = 0;
	do{

		QFileInfo fileInfo = list.at(i);
		/*	.代表当前目录,也就是你目前打开的那个文件夹,
		.. 代表上一级目录*/
		if (fileInfo.fileName() == "." | fileInfo.fileName() == "..")   //去处获得的2个fileInfo.fileName中的不相关文件(文件夹)
		{
			i++;
			continue;
		}
		bool bisDir = fileInfo.isDir();
		if (bisDir)
		{
			nFiles++;
			//qDebug() << fileInfo.path() + fileInfo.fileName();       //打印出子文件夹
			MainWidget::FindFile(fileInfo.filePath());         //递归调用,获取文件夹中的文件
		}
		else{
			nFiles++;
			QStringList filters;
			format = fileInfo.fileName().right(3);
			/*还是用字符串滤波器,通配符比较正式!*/
			if (format == "jpg" || format == "png" || format == "bmp")//只取了文件名字符串的右3位,只考虑了小写字母
			{
				QString imageFilePath = fileInfo.path() + "/" + fileInfo.fileName();
				//qDebug() << fileInfo.path() + "/" + fileInfo.fileName();
				ui.imageFileListWidget->addItem(imageFilePath);
			}
		}
		i++;
	} while (i < list.size());

	return true;
}

2.

列表数据结构的应用,只在一端进行插入的受限线性表(或者栈的应用,先进后出,将一个字符序列逆序)

知识:QList Class

参考:http://doc.qt.io/qt-5/qlist.html

QTreeView

参考:http://doc.qt.io/archives/qtjambi-4.5.2_01/com/trolltech/qt/gui/QTreeView.html

知识:模型视图编程框架!

场景:

比如这样一个文件路径:C:\接触网数据库20180802\焦柳线_上行_2018-07-04_08-50_小烟墩至漳河#278_\1_平腕臂1&定位器\1-1.jpg

从界面上获取的当前Item项QModelIndex为1-1.jpg,要往回溯,直到回溯到进入该文件夹的顶层文件目录接触网数据库20180802

说白了就是将路径的字符串逆序:

函数:OnlineTreeViewSingleClick

功能:从当前选择的文件的叶子节点回溯,获得其完整的路径名,并用QImage读入图像文件并resize后转为pixmap并显示在界面的一个label上:

/*TreeView视图的单击事件处理函数:要显示图片,必须要将路径拼接起来,并识别是图像文件!*/
void MainWidget::OnlineTreeViewSingleClick(const QModelIndex & index)
{

	QModelIndex currentIndex = index;

	QList<QString> imageFilePath;
	imageFilePath.clear();

	while (currentIndex.data().toString() != currentPath)
	{
		imageFilePath.push_front(currentIndex.data().toString());
		imageFilePath.push_front("/");
		currentIndex = currentIndex.parent();

	}
	imageFilePath.push_front(srcDir.absolutePath());

	QList<QString>::iterator iter;
	for (iter = imageFilePath.begin(); iter != imageFilePath.end(); iter++)
	{
		imagePath +=(*iter);
	}

	qDebug() << "imagePath=" << imagePath << endl;


	//imagePath = srcDirPath +"/"+ parentIndex.data().toString() +"/"+ index.data().toString();
	/*这样些有个bug,父目录的级数被写死了,再与全局的目录结合的话出现问题!
	
	
	2018年8月2日17点41分:修复这个bug,,修复后在任意一级目录都可以实现鼠标点击选中图像的绝对路径的获取!
	注意:
	1.对目录结构要了解,会用QDir类,
	2.对TreeView 树形视图要了解,会使用QModelIndex 索引类和父类定位选中的图像。。。

	3.上面代码中的:
	while (currentIndex.data().toString() != currentPath)
	{
	imageFilePath.push_front(currentIndex.data().toString());
	imageFilePath.push_front("/");
	currentIndex = currentIndex.parent();

	}
	imageFilePath.push_front(srcDir.absolutePath());
	这个while循环实现当前选中节点与进入时对话框选取的路径相对比,一直从叶子节点往上回溯到这个当前目录,并形成图像文件的绝对路径!

	*/


	QString format = imagePath.right(3);
	/*还是用字符串滤波器,通配符比较正式!判断是图像数据再显示!*/
	if (format == "jpg" || format == "png" || format == "bmp")//只取了文件名字符串的右3位,只考虑了小写字母
	{
		qDebug() << "imagePath=" << imagePath << endl;
		QPixmap pixmap;
		QImage image;
		image.load(imagePath);
		image = image.scaled(ui.imageLable->size());//该图太大,resize到界面上的imageLable的尺寸

		/* static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
		fromImage()函数返回的是QPixmap对象,所有要用pixmap来借该对象!*/
		pixmap = pixmap.fromImage(image);

		ui.imageLable->setPixmap(pixmap);
		ui.imageLable->show();
	}


	//QAbstractItemModel* m = (QAbstractItemModel*)index.model();
	//for (int columnIndex = 0; columnIndex < m->columnCount(); columnIndex++)
	//{
	//	QModelIndex x = m->index(index.row(), columnIndex);

	//	QString s = x.data().toString();
	//	qDebug() <<  s << endl;
	//}


	imagePath.clear();
}

 

完整代码包括这个界面类的定义

实现递归读取所有的图像文件,并能在界面上生成树形目录结构(用的是QTreeView),鼠标单击某张图像文件时在界面上显示出来:

 

头文件:mainwidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QtWidgets/QMainWindow>
#include <QDir>
#include <QFileDialog>
#include <QDebug>
#include <QDirIterator>
#include <vector>
#include <iostream>
#include "ui_mainwidget.h"
#include<QListWidgetItem>
#include<QFileSystemModel>
#include<QTreeView>


class MainWidget : public QMainWindow
{
	Q_OBJECT

public:
	MainWidget(QWidget *parent = 0);
	~MainWidget();

	bool FindFile(const QString & path);



private:
	Ui::MainWidgetClass ui;
	QString srcDirPath;
	QString currentPath;
	QString imagePath;
	QDir srcDir;
	QStringList imageList;

	QVector<QString> imageFilePath;
	QLabel* imageLabel;

private slots:
	void on_toolButton_read_clicked();
	void on_toolButton_save_clicked();
	void on_pushButton_loadImage_clicked();

	void imageListWidgetItemClicked(QListWidgetItem * item);

	void OnlineTreeViewSingleClick(const QModelIndex & index);
	
};

#endif // MAINWIDGET_H

mainwidget.cpp
 

#include "mainwidget.h"
#include<qpainter.h>
#include<QTreeView>
#include<QDirModel>
QString file_path;
int nFiles = 0;
bool isFindFile;

MainWidget::MainWidget(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	connect(ui.imageFileListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(imageListWidgetItemClicked(QListWidgetItem*)));
	connect(ui.treeView, SIGNAL(clicked(const QModelIndex)), this, SLOT(OnlineTreeViewSingleClick(const QModelIndex)));


}

MainWidget::~MainWidget()
{

}


//用来获取文件夹中所有图像的名称,方便插入数据库
QStringList getFileNames(const QString &path)
{
	QDir dir(path);
	QStringList nameFilters;
	nameFilters << "*.jpg" << "*.png"<<"*.bmp";
	QStringList files = dir.entryList(nameFilters, QDir::Files | QDir::Readable, QDir::Name);
	return files;
}

//选择要读取的图像数据:toolButton_read按钮的单击事件处理函数
void MainWidget::on_toolButton_read_clicked()
{
	srcDirPath = QFileDialog::getExistingDirectory(
	this, "choose src Directory",
	"/");

	if (srcDirPath.isEmpty())
	{
		return;
	}
	else
	{
		qDebug() << "srcDirPath=" << srcDirPath;
		
		srcDir.cd(srcDirPath);

		currentPath = srcDir.dirName();
		qDebug() << "srcDir.dirName()=" << srcDir.dirName()<<endl;


		qDebug() << "srcDir.absolutePath()=" << srcDir.absolutePath() << endl;



		ui.comboBox_read->addItem(srcDirPath);
		//srcDirPath += "/";
		//imageList = getFileNames(srcDirPath);
	}

	//QFileSystemModel model;
	//model.setRootPath(srcDirPath);
	//QTreeView treeView;
	//ui.treeView.setModel(&model);
	//ui.treeView.setRootIndex(model.index(srcDirPath));
	//ui.treeView.show();



	QDirModel *model = new QDirModel();
	ui.treeView->setModel(model);
	ui.treeView->setRootIndex(model->index(srcDirPath));



	isFindFile = FindFile(srcDirPath);

}



/*参考QDir类:http://doc.qt.io/qt-5/qdir.html */
//采用递归的方式,获取文件夹中子文件夹下所有的图像文件。


/*
FindFile()函数
输入参数:顶层文件目录路径名称QString类型
输出:再UI界面的ListWidget中列出所有的文件全路径(绝对路径)
*/
bool MainWidget::FindFile(const QString & path)
{
	QString format;
	QDir dir(path);/* Windows系统上会将Windows的文件路径上的/转换为\  */
	if (!dir.exists())
		return false;
	dir.setFilter(QDir::Dirs | QDir::Files);/*因为是用递归,所以必须有目录和文件两种过滤项*/
	dir.setSorting(QDir::DirsFirst);/*QDir::DirsFirst	0x04	Put the directories first, then the files.*/
	QFileInfoList list = dir.entryInfoList();  //获的文件夹下的所有文件列表,实际获取的多2个

	if (list.empty())
		return false;
	/*
	QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, QDir::Filters filters = NoFilter, QDir::SortFlags sort = NoSort) const

	Returns a list of QFileInfo objects for all the files and directories in the directory, ordered according to the name 
	
	and attribute filters previously set with setNameFilters() and setFilter(), and sorted according to the flags set with setSorting().

	The name filter, file attribute filter, and sorting specification can be overridden using the nameFilters, filters, and sort arguments.

	Returns an empty list if the directory is unreadable, does not exist, or if nothing matches the specification.

	See also entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), and exists().
*/

	int i = 0;
	do{

		QFileInfo fileInfo = list.at(i);
		/*	.代表当前目录,也就是你目前打开的那个文件夹,
		.. 代表上一级目录*/
		if (fileInfo.fileName() == "." | fileInfo.fileName() == "..")   //去处获得的2个fileInfo.fileName中的不相关文件(文件夹)
		{
			i++;
			continue;
		}
		bool bisDir = fileInfo.isDir();
		if (bisDir)
		{
			nFiles++;
			//qDebug() << fileInfo.path() + fileInfo.fileName();       //打印出子文件夹
			MainWidget::FindFile(fileInfo.filePath());         //递归调用,获取文件夹中的文件
		}
		else{
			nFiles++;
			QStringList filters;
			format = fileInfo.fileName().right(3);
			/*还是用字符串滤波器,通配符比较正式!*/
			if (format == "jpg" || format == "png" || format == "bmp")//只取了文件名字符串的右3位,只考虑了小写字母
			{
				QString imageFilePath = fileInfo.path() + "/" + fileInfo.fileName();
				//qDebug() << fileInfo.path() + "/" + fileInfo.fileName();
				ui.imageFileListWidget->addItem(imageFilePath);
			}
		}
		i++;
	} while (i < list.size());

	return true;
}



//选择要保存缺陷表单的文件夹路径
void MainWidget::on_toolButton_save_clicked()
{
	srcDirPath = QFileDialog::getExistingDirectory(
		this, "choose src Directory",
		"/");

	if (srcDirPath.isEmpty())
	{
		return;
	}
	else
	{
		qDebug() << "srcDirPath=" << srcDirPath;
		ui.comboBox_save->addItem(srcDirPath);
		srcDirPath += "/";

	}
}

void MainWidget::on_pushButton_loadImage_clicked()
{

	
}



/*单击ListWidget中的一个项时其会发出SIGNAL(itemClicked(QListWidgetItem*)),该信号与这里的槽函数connect一下。
connect(ui.imageFileListWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(imageListWidgetItemClicked(QListWidgetItem*)));
*/
void MainWidget::imageListWidgetItemClicked(QListWidgetItem * item)
{
	int currenRow = ui.imageFileListWidget->currentRow();//当前单击选中ListWidget控件的行号(第几行)
	
	//ui.imagePathLineEdit->setText(tr("%1").arg(currenRow));//将这个行号显示在lineText编辑框中
	QString imageListWidgetItem = item->text();
	ui.imagePathLineEdit->setText(imageListWidgetItem);



	QPixmap pixmap;
	QImage image;
	image.load(imageListWidgetItem);
	image = image.scaled(ui.imageLable->size());//该图太大,resize到界面上的imageLable的尺寸

	/* static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
	fromImage()函数返回的是QPixmap对象,所有要用pixmap来借该对象!*/
	pixmap=pixmap.fromImage(image);

	ui.imageLable->setPixmap(pixmap);
	ui.imageLable->show();
	//imageLabel->setPixmap(pixmap);


}



/*TreeView视图的单击事件处理函数:要显示图片,必须要将路径拼接起来,并识别是图像文件!*/
void MainWidget::OnlineTreeViewSingleClick(const QModelIndex & index)
{
	//qDebug() << "index.data().toString()="<<index.data().toString() << endl;

	//QModelIndex parentIndex = index.parent();
	//qDebug() << "parentIndex.data().toString()="<<parentIndex.data().toString() << endl;

	//QModelIndex pparentIndex = parentIndex.parent();
	//qDebug() << "pparentIndex.data().toString()="<<pparentIndex.data().toString() << endl;

	//QModelIndex ppparentIndex = pparentIndex.parent();
	//qDebug() << "ppparentIndex.data().toString()=" << ppparentIndex.data().toString() << endl;

	QModelIndex currentIndex = index;

	QList<QString> imageFilePath;
	imageFilePath.clear();

	while (currentIndex.data().toString() != currentPath)
	{
		imageFilePath.push_front(currentIndex.data().toString());
		imageFilePath.push_front("/");
		currentIndex = currentIndex.parent();

	}
	imageFilePath.push_front(srcDir.absolutePath());

	QList<QString>::iterator iter;
	for (iter = imageFilePath.begin(); iter != imageFilePath.end(); iter++)
	{
		imagePath +=(*iter);
	}

	qDebug() << "imagePath=" << imagePath << endl;


	//imagePath = srcDirPath +"/"+ parentIndex.data().toString() +"/"+ index.data().toString();
	/*这样些有个bug,父目录的级数被写死了,再与全局的目录结合的话出现问题!
	
	
	2018年8月2日17点41分:修复这个bug,,修复后在任意一级目录都可以实现鼠标点击选中图像的绝对路径的获取!
	注意:
	1.对目录结构要了解,会用QDir类,
	2.对TreeView 树形视图要了解,会使用QModelIndex 索引类和父类定位选中的图像。。。

	3.上面代码中的:
	while (currentIndex.data().toString() != currentPath)
	{
	imageFilePath.push_front(currentIndex.data().toString());
	imageFilePath.push_front("/");
	currentIndex = currentIndex.parent();

	}
	imageFilePath.push_front(srcDir.absolutePath());
	这个while循环实现当前选中节点与进入时对话框选取的路径相对比,一直从叶子节点往上回溯到这个当前目录,并形成图像文件的绝对路径!

	*/


	QString format = imagePath.right(3);
	/*还是用字符串滤波器,通配符比较正式!判断是图像数据再显示!*/
	if (format == "jpg" || format == "png" || format == "bmp")//只取了文件名字符串的右3位,只考虑了小写字母
	{
		qDebug() << "imagePath=" << imagePath << endl;
		QPixmap pixmap;
		QImage image;
		image.load(imagePath);
		image = image.scaled(ui.imageLable->size());//该图太大,resize到界面上的imageLable的尺寸

		/* static QPixmap fromImage(const QImage &image, Qt::ImageConversionFlags flags = Qt::AutoColor);
		fromImage()函数返回的是QPixmap对象,所有要用pixmap来借该对象!*/
		pixmap = pixmap.fromImage(image);

		ui.imageLable->setPixmap(pixmap);
		ui.imageLable->show();
	}


	//QAbstractItemModel* m = (QAbstractItemModel*)index.model();
	//for (int columnIndex = 0; columnIndex < m->columnCount(); columnIndex++)
	//{
	//	QModelIndex x = m->index(index.row(), columnIndex);

	//	QString s = x.data().toString();
	//	qDebug() <<  s << endl;
	//}


	imagePath.clear();
}

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值