在日常工作中,我们经常需要在大量的文件中查找特定的内容或者文件名,这个过程可能非常耗时和繁琐。为了提高工作效率,我们可以开发一款简单而高效的文件搜索工具。本文将介绍如何使用Python和PyQt来开发这样一个工具,并提供设计思路、分阶段代码示例以及最终的完整代码示例。
1.设计思路:
- 用户界面设计:使用PyQt库来创建用户界面,通过添加输入框、搜索按钮和结果显示框等元素,实现用户输入搜索内容并显示搜索结果的功能。
 - 文件搜索算法:通过递归遍历文件系统中的所有文件和文件夹,并与搜索内容进行匹配,将匹配到的文件路径保存下来。
 - 文件类型筛选:可以根据用户需求对搜索结果进行文件类型的筛选,只显示某些特定类型的文件。
 - 美化效果:使用PyQt的样式表功能来美化用户界面,使其更加美观和易用。
 
2.分阶段代码示例:
2.1创建用户界面
import sys
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QLineEdit, QPushButton
class FileSearchTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('文件搜索工具')
        self.resize(400, 300)
        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)
        self.search_label = QLabel('搜索内容:', self.central_widget)
        self.search_label.setGeometry(20, 20, 80, 20)
        self.search_input = QLineEdit(self.central_widget)
        self.search_input.setGeometry(100, 20, 200, 20)
        self.search_button = QPushButton('搜索', self.central_widget)
        self.search_button.setGeometry(320, 20, 60, 20)
        self.result_label = QLabel('搜索结果:', self.central_widget)
        self.result_label.setGeometry(20, 60, 80, 20)
        self.result_display = QLineEdit(self.central_widget)
        self.result_display.setGeometry(100, 60, 280, 200)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = FileSearchTool()
    window.show()
    sys.exit(app.exec_())
 
2.2实现文件搜索算法
import os
def search_files(root_dir, search_content):
    result = []
    for dir_path, _, file_names in os.walk(root_dir):
        for file_name in file_names:
            file_path = os.path.join(dir_path, file_name)
            if search_content in file_path:
                result.append(file_path)
    return result
 
 
2.3实现搜索按钮的点击事件
self.search_button.clicked.connect(self.search_files)
def search_files(self):
    search_content = self.search_input.text()
    root_dir = 'C:/Users/'
    result = search_files(root_dir, search_content)
    self.result_display.setText('\n'.join(result))
 
2.4添加文件类型筛选功能
def search_files(self):
    search_content = self.search_input.text()
    root_dir = 'C:/Users/'
    result = search_files(root_dir, search_content)
    
    file_type_filter = '.txt' # 指定文件类型
    filtered_result = [file_path for file_path in result if file_path.endswith(file_type_filter)]
    
    self.result_display.setText('\n'.join(filtered_result))
 
2.5最终的完整代码示例:
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QLineEdit, QPushButton
def search_files(root_dir, search_content):
    result = []
    for dir_path, _, file_names in os.walk(root_dir):
        for file_name in file_names:
            file_path = os.path.join(dir_path, file_name)
            if search_content in file_path:
                result.append(file_path)
    return result
class FileSearchTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('文件搜索工具')
        self.resize(400, 300)
        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)
        self.search_label = QLabel('搜索内容:', self.central_widget)
        self.search_label.setGeometry(20, 20, 80, 20)
        self.search_input = QLineEdit(self.central_widget)
        self.search_input.setGeometry(100, 20, 200, 20)
        self.search_button = QPushButton('搜索', self.central_widget)
        self.search_button.setGeometry(320, 20, 60, 20)
        self.result_label = QLabel('搜索结果:', self.central_widget)
        self.result_label.setGeometry(20, 60, 80, 20)
        self.result_display = QLineEdit(self.central_widget)
        self.result_display.setGeometry(100, 60, 280, 200)
        self.search_button.clicked.connect(self.search_files)
    def search_files(self):
        search_content = self.search_input.text()
        root_dir = 'C:/Users/'
        result = search_files(root_dir, search_content)
        
        file_type_filter = '.txt' # 指定文件类型
        filtered_result = [file_path for file_path in result if file_path.endswith(file_type_filter)]
        
        self.result_display.setText('\n'.join(filtered_result))
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = FileSearchTool()
    window.show()
    sys.exit(app.exec_())
 
让我们看看运行效果如何

3.优化卡顿
额。。。。居然卡住了,原因是因为遍历文件阻塞的当前主线程,导致界面显示出现了问题,我们做一下优化,将搜索过程放进线程中去实现,以确保搜索过程不会阻塞用户界面的响应。
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QLineEdit, QPushButton
from PyQt5.QtCore import QThread, pyqtSignal
def search_files(root_dir, search_content):
    result = []
    for dir_path, _, file_names in os.walk(root_dir):
        for file_name in file_names:
            file_path = os.path.join(dir_path, file_name)
            if search_content in file_path:
                result.append(file_path)
    return result
class SearchThread(QThread):
    search_finished = pyqtSignal(list)
    def __init__(self, root_dir, search_content):
        super().__init__()
        self.root_dir = root_dir
        self.search_content = search_content
    def run(self):
        result = search_files(self.root_dir, self.search_content)
        self.search_finished.emit(result)
class FileSearchTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('文件搜索工具')
        self.resize(400, 300)
        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)
        self.search_label = QLabel('搜索内容:', self.central_widget)
        self.search_label.setGeometry(20, 20, 80, 20)
        self.search_input = QLineEdit(self.central_widget)
        self.search_input.setGeometry(100, 20, 200, 20)
        self.search_button = QPushButton('搜索', self.central_widget)
        self.search_button.setGeometry(320, 20, 60, 20)
        self.result_label = QLabel('搜索结果:', self.central_widget)
        self.result_label.setGeometry(20, 60, 80, 20)
        self.result_display = QLineEdit(self.central_widget)
        self.result_display.setGeometry(100, 60, 280, 200)
        self.search_button.clicked.connect(self.start_search_thread)
    def start_search_thread(self):
        search_content = self.search_input.text()
        root_dir = 'C:/Users/'
        self.search_thread = SearchThread(root_dir, search_content)
        self.search_thread.search_finished.connect(self.update_results)
        self.search_thread.start()
    def update_results(self, result):
        self.result_display.setText('\n'.join(result))
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = FileSearchTool()
    window.show()
    sys.exit(app.exec_())
 
使用QThread类创建了一个名为SearchThread的子类,在其run方法中执行文件搜索算法。 


果然,经过优化后界面不再卡住了,但是怎么看总觉得少点什么,我们不知道搜索的进度怎么样,体验感不是很好。
4.优化搜索等待效果
再优化一下,搜索的过程中界面要有动画加载等待效果
import sys
import os
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QLabel, QLineEdit, QPushButton, QVBoxLayout, QHBoxLayout, QProgressBar, QTextEdit
from PyQt5.QtCore import QThread, pyqtSignal
def search_files(root_dir, search_content, progress_callback):
    result = []
    total_files = sum(len(files) for _, _, files in os.walk(root_dir))
    progress = 0
    for dir_path, _, file_names in os.walk(root_dir):
        for file_name in file_names:
            file_path = os.path.join(dir_path, file_name)
            if search_content in file_path:
                result.append(file_path)
            progress += 1
            progress_callback.emit((progress / total_files) * 100)
    return result
class SearchThread(QThread):
    search_finished = pyqtSignal(list)
    progress_updated = pyqtSignal(int)
    def __init__(self, root_dir, search_content):
        super().__init__()
        self.root_dir = root_dir
        self.search_content = search_content
    def run(self):
        result = search_files(self.root_dir, self.search_content, self.progress_updated)
        self.search_finished.emit(result)
class FileSearchTool(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle('文件搜索工具')
        self.resize(400, 300)
        self.central_widget = QWidget(self)
        self.setCentralWidget(self.central_widget)
        self.layout = QVBoxLayout(self.central_widget)
        self.search_label = QLabel('搜索内容:')
        self.layout.addWidget(self.search_label)
        self.search_input = QLineEdit()
        self.layout.addWidget(self.search_input)
        self.search_button = QPushButton('搜索')
        self.layout.addWidget(self.search_button)
        self.progress_bar = QProgressBar()
        self.layout.addWidget(self.progress_bar)
        self.result_label = QLabel('搜索结果:')
        self.layout.addWidget(self.result_label)
        self.result_display = QTextEdit()
        self.result_display.setReadOnly(True)
        self.layout.addWidget(self.result_display)
        self.search_button.clicked.connect(self.start_search_thread)
    def start_search_thread(self):
        self.result_display.clear()
        self.progress_bar.setValue(0)
        search_content = self.search_input.text()
        root_dir = 'C:/Users/'
        self.search_thread = SearchThread(root_dir, search_content)
        self.search_thread.search_finished.connect(self.update_results)
        self.search_thread.progress_updated.connect(self.update_progress_bar)
        self.search_thread.start()
    def update_results(self, result):
        self.result_display.setPlainText('\n'.join(result))
    def update_progress_bar(self, value):
        self.progress_bar.setValue(value)
if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = FileSearchTool()
    window.show()
    sys.exit(app.exec_()) 


经过优化后,效果还算不错了。
5.总结
最后让我们总结一下完整代码的实现思路,这段代码是一个简单的基于 PyQt5 的文件搜索工具。
-  
导入必要的模块:代码一开始导入了
sys和os模块,以及 PyQt5 中的一些类和模块,如QApplication,QMainWindow,QWidget,QLabel,QLineEdit,QPushButton,QVBoxLayout,QHBoxLayout,QProgressBar,QTextEdit,以及QThread和pyqtSignal等。 -  
search_files 函数:这是一个用于在指定目录中搜索包含特定内容的文件的函数。它接受三个参数:
root_dir(搜索的根目录)、search_content(要搜索的内容)和progress_callback(用于更新进度条的回调函数)。该函数遍历指定目录及其子目录中的所有文件,如果文件名中包含搜索内容,则将其路径添加到结果列表中,并通过进度回调函数更新搜索进度。 -  
SearchThread 类:这是一个继承自
QThread的自定义线程类,用于在后台执行文件搜索任务。它包含两个信号:search_finished(搜索完成信号,发送搜索结果列表)和progress_updated(进度更新信号,发送搜索进度值)。在run方法中调用了search_files函数执行实际的文件搜索任务,并在搜索过程中通过进度更新信号更新搜索进度。 -  
FileSearchTool 类:这是主窗口类,继承自
QMainWindow。它包含了用于构建用户界面的各种组件,如搜索输入框、搜索按钮、进度条和结果显示框等。当用户点击搜索按钮时,会调用start_search_thread方法启动文件搜索线程,并连接信号search_finished和progress_updated到对应的槽函数,用于更新搜索结果和搜索进度。 -  
主程序:在主程序中创建了一个
QApplication实例和FileSearchTool实例,然后显示主窗口,并通过sys.exit(app.exec_())运行应用程序的事件循环。 
整体来说,这段代码实现了一个简单的文件搜索工具,用户可以输入要搜索的内容,然后点击搜索按钮,程序会在指定目录中搜索包含该内容的文件,并实时显示搜索进度和搜索结果。