在python学习过程中有一次需要进行GUI 的绘制,

而在python中有自带的库tkinter可以用来简单的GUI编写,于是转而学习tkinter库的使用。

学以致用,现在试着编写一个简单的磁文件搜索工具,

方法就是将指定的文件夹进行扫描遍历,把其中的每个文件路径数据存入数据库,

然后使用数据库搜索文件就很快捷。实现的效果大致如下:

整个程序分为大致几个模块:

主界面的绘制,

指定文件夹功能函数,

搜索文件功能函数,

ui线程与扫描线程同步函数,

扫描线程工作函数

要实现扫描文件功能时,

导入了一个这样的模块 disk.py

这个模块实现的功能就是将指定文件夹下的所有文件遍历,并将路径和所在盘符存到一个列表中返回

import os
import os.path as ptdef scan_file(path):result = []for root, dirs, files in os.walk(path):for f in files:file_path = pt.abspath(pt.join(root, f))result.append((file_path, file_path[0]))  # 保存路径与盘符return result

然后我们需要将扫描到的文件存入到数据库中,

因此需要编写数据库模块 datebase.py

import sqlite3class DataMgr:def __init__(self):# 创建或打开一个数据库# check_same_thread 属性用来规避多线程操作数据库的问题self.conn = sqlite3.connect("file.db", check_same_thread=False)# 建表self.conn.execute('create table if not exists disk_table(' 'id integer primary key autoincrement,' 'file_path text,' 'drive_letter text)')# 创建索引 用来提高搜索速度self.conn.execute('create index if not exists index_path on disk_table(file_path)')# 批量插入数据def batch_insert(self, data):for line in data:self.conn.execute('insert into disk_table values (null,?,?)', line)self.conn.commit()# 模糊搜索def query(self, key):cursor = self.conn.cursor()cursor.execute("select file_path from disk_table where file_path like ?", ('%{0}%'.format(key),))r = [row[0] for row in cursor]cursor.close()return rdef close(self):self.conn.close()

还需要一个额外的模块为 progressbar.py

这个模块的功能是在扫描时弹出一个进度条窗口,

使得GUI功能看起来更完善

from tkinter import *
from tkinter import ttkclass GressBar:def start(self):top = Toplevel()  # 弹出式窗口,实现多窗口时经常用到self.master = toptop.overrideredirect(True)  # 去除窗体的边框top.title("进度条")Label(top, text="正在扫描选定路径的文件,请稍等……", fg="blue").pack(pady=2)prog = ttk.Progressbar(top, mode='indeterminate', length=200)  # 创建进度条prog.pack(pady=10, padx=35)prog.start()top.resizable(False, False)  # 参数为false表示不允许改变窗口尺寸
        top.update()# 计算窗口大小,使显示在屏幕中央curWidth = top.winfo_width()curHeight = top.winfo_height()scnWidth, scnHeight = top.maxsize()tmpcnf = '+%d+%d' % ((scnWidth - curWidth) / 2, (scnHeight - curHeight) / 2)top.geometry(tmpcnf)top.mainloop()def quit(self):if self.master:self.master.destroy()

主体的search.py 代码:

  1 from tkinter import *
  2 from tkinter import ttk
  3 import tkinter.filedialog as dir
  4 import queue
  5 import threading
  6 import progressbar
  7 import disk
  8 from database import DataMgr
  9
 10
 11 class SearchUI:
 12
 13     def __init__(self):
 14         # 创建一个消息队列
 15         self.notify_queue = queue.Queue()
 16         root = Tk()
 17         self.master = root
 18         self.create_menu(root)
 19         self.create_content(root)
 20         self.path = 'D:'
 21         root.title('the search tool')
 22         root.update()
 23         # 在屏幕中心显示窗体
 24         curWidth = root.winfo_width()
 25         curHeight = root.winfo_height()
 26         scnWidth, scnHeight = root.maxsize()  # 得到屏幕的宽度和高度
 27         tmpcnf = '+%d+%d' % ((scnWidth - curWidth)/2, (scnHeight-curHeight)/2)
 28         root.geometry(tmpcnf)
 29
 30         # 创建一个进度条对话框实例
 31         self.gress_bar = progressbar.GressBar()
 32
 33         # 创建一个数据库的实例
 34         self.data_mgr = DataMgr()
 35
 36         # 在UI线程启动消息队列循环
 37         self.process_msg()
 38         root.mainloop()
 39
 40     # ui线程与扫描线程同步
 41     def process_msg(self):
 42         # after方法,相当于一个定时器,
 43         # 第一个参数是时间的毫秒值,
 44         # 第二个参数指定执行一个函数
 45         self.master.after(400, self.process_msg)
 46         # 这样我们就在主线程建立了一个消息队列,
 47         # 每隔一段时间去消息队列里看看,
 48         # 有没有什么消息是需要主线程去做的,
 49         # 有一点需要特别注意,
 50         # 主线程消息队列里也不要干耗时操作,
 51         # 该队列仅仅用来更新UI。
 52         while not self.notify_queue.empty():
 53             try:
 54                 msg = self.notify_queue.get()
 55                 if msg[0] == 1:
 56                     self.gress_bar.quit()
 57
 58             except queue.Empty:
 59                 pass
 60
 61     # 扫描线程工作
 62     def execute_asyn(self):
 63         # 定义一个scan函数,放入线程中去执行耗时扫描
 64         def scan(_queue):
 65             if self.path:
 66                 paths = disk.scan_file(self.path)  # 位于disk.py
 67                 self.data_mgr.batch_insert(paths)  # 位于database.py
 68
 69             _queue.put((1,))
 70         th = threading.Thread(target=scan, args=(self.notify_queue,))
 71         th.setDaemon(True)  # 设置为守护进程
 72         th.start()
 73
 74         self.gress_bar.start()
 75
 76     # 菜单绘制
 77     def create_menu(self, root):
 78         menu = Menu(root)  # 创建菜单
 79
 80         # 二级菜单
 81         file_menu = Menu(menu, tearoff=0)
 82         file_menu.add_command(label='设置路径', command=self.open_dir)
 83         file_menu.add_separator()
 84         file_menu.add_command(label='扫描', command=self.execute_asyn)
 85
 86         about_menu = Menu(menu, tearoff=0)
 87         about_menu.add_command(label='version1.0')
 88
 89         # 在菜单栏中添加菜单
 90         menu.add_cascade(label='文件', menu=file_menu)
 91         menu.add_cascade(label='关于', menu=about_menu)
 92         root['menu'] = menu
 93
 94     # 主界面绘制
 95     def create_content(self, root):
 96         lf = ttk.LabelFrame(root, text='文件搜索')
 97         lf.pack(fill=X, padx=15, pady=8)
 98
 99         top_frame = Frame(lf)
100         top_frame.pack(fill=X, expand=YES, side=TOP, padx=15, pady=8)
101
102         self.search_key = StringVar()
103         ttk.Entry(top_frame, textvariable=self.search_key, width=50).pack(fill=X, expand=YES, side=LEFT)
104         ttk.Button(top_frame, text="搜索", command=self.search_file).pack(padx=15, fill=X, expand=YES)
105
106         bottom_frame = Frame(lf)
107         bottom_frame.pack(fill=BOTH, expand=YES, side=TOP, padx=15, pady=8)
108
109         band = Frame(bottom_frame)
110         band.pack(fill=BOTH, expand=YES, side=TOP)
111
112         self.list_val = StringVar()
113         listbox = Listbox(band, listvariable=self.list_val, height=18)
114         listbox.pack(side=LEFT, fill=X, expand=YES)
115
116         vertical_bar = ttk.Scrollbar(band, orient=VERTICAL, command=listbox.yview)
117         vertical_bar.pack(side=RIGHT, fill=Y)
118         listbox['yscrollcommand'] = vertical_bar.set
119
120         horizontal_bar = ttk.Scrollbar(bottom_frame, orient=HORIZONTAL, command=listbox.xview)
121         horizontal_bar.pack(side=BOTTOM, fill=X)
122         listbox['xscrollcommand'] = horizontal_bar.set
123
124         # 给list动态设置数据,set方法传入一个元组
125         self.list_val.set(('等待搜索',))
126
127     # 搜索文件
128     def search_file(self):
129         if self.search_key.get():
130             result_data = self.data_mgr.query(self.search_key.get())
131             if result_data:
132                  self.list_val.set(tuple(result_data))
133
134     # 指定文件夹
135     def open_dir(self):
136         d = dir.Directory()
137         self.path = d.show(initialdir=self.path)
138
139
140 if __name__ == '__main__':
141     SearchUI()

问题总结:

1.UI线程负责界面的绘制与更新,如果在UI线程中进行耗时操作,会影响界面的流畅性,所以需要异步线程。

此时的问题在于UI的主线程与异步线程的通信问题,为什么一定要两个线程通信?

因为在大多数GUI界面编程中,异步线程都是不能对当前界面进行操作更新的,否则会引起界面混乱。

可以简单的理解成  如果异步线程也操作主界面,则两个线程对相同资源进行操作,就会导致混乱。

接下来的问题是tkinter中没有提供接口进行线程通信,因此我们通过消息队列的方式来同步线程,用到的类为Queue。

项目中当在消息队列中检索到消息为元组(1, )时,说明子线程(扫描)已经结束了,告知主线程可以结束子线程了。

2.扫描文件夹时需要将所选文件夹中的所有文件遍历一遍,发现python中提供了方法os.walk(path), 可以直接达到这一效果,所以说python在写代码时确实提供了方便。

3.该磁盘搜索工具用到的原理是将文件路径存到数据库中,再进行检索。 选用的数据库为sqlite,已经可以满足该项目的要求。在主线程创建数据库,子线程操作数据库,有可能出现问题,因此设置check_same_thread = false 来拒绝多线程的访问。

4.在进行GUI编程时,打算在扫描等待时添加一个进度条显示窗口,也就需要多窗口,用到了toplevel,表现为一个弹出式窗口,在使用toplevel时,要注意首先需要一个根窗口。

转载于:https://www.cnblogs.com/blsx/p/11239679.html

python实现文件搜索工具(简易版)相关推荐

  1. python 简单检索器_python实现文件搜索工具(简易版)

    在python学习过程中有一次需要进行GUI 的绘制, 而在python中有自带的库tkinter可以用来简单的GUI编写,于是转而学习tkinter库的使用. 学以致用,现在试着编写一个简单的磁文件 ...

  2. 文件搜索工具(Python实现)

    文章目录 文件搜索工具介绍 代码实现 实现思路 os.walk函数 os.path.join函数 代码整体编写 打包成exe程序 效果展示 文件搜索工具介绍 文件搜索工具能够基于名称快速定位匹配的文件 ...

  3. 深挖你硬盘里的见不得人的【学习资料】,Python制作一款文件搜索工具

    前言 今天来教大家做一个文件搜索工具,专门来找你电脑里的[学习资料],嘿嘿 开发环境 解释器: Python 3.8.8 | Anaconda, Inc. 编辑器: pycharm 专业版 先演示效果 ...

  4. PDF Search for Mac(PDF文件搜索工具)

    本次小编为您带来PDF Search for Mac破解版,这是Mac平台上一款可以帮助用户快速搜索文档,在Mac上从数千份文档中,快速搜索出你所需要的文档的PDF文件搜索工具!有了PDF Searc ...

  5. Atitit.文件搜索工具 attilax 总结

    Atitit.文件搜索工具 attilax 总结 1. 指定目录按照体积大小精确搜索1 1.1. File Seeker 4.5 版本的可以,3.5版本的不行..1 2. 按照文件内容搜索1 2.1. ...

  6. gorm preload 搜索_macOS系统本地文件搜索工具

    Find Any File Mac可以准确快速地查找本次磁盘甚至是本地隐藏磁盘上的任何文件,Find Any File Mac不使用数据库,而是使用文件系统驱动程序的快速搜索操作,包括能够搜索到通常隐 ...

  7. gorm preload 搜索_文件太多忘记了文件放在什么地方?那你可以试试这款文件搜索工具...

    忘记了文件放在什么地方?文件太多不能一下子找到?那么你也许可以试试这款软件--ProFind for mac版,这是一款适用于macOS系统的文件搜索工具,它具有强大的功能和出色的性能,可为macOS ...

  8. ls mac 显示最近修改日期_Find Any File for Mac(Mac本地文件搜索工具)

    今天小编给大家带来的Find Any File mac是Mac平台上的一款本地文件搜索查找工具,可以让你在本地磁盘上快速搜索.查找你需要的文件.甚至是隐藏文件都逃不出Find Any File mac ...

  9. python做的游戏放到微信_【1、 创建一个python的文件,运行后,文字版方式模拟微信游戏“跳一跳?】...

    python脚本学习过程推荐 学习流程: 一:打础 1.找到合适的书籍(推荐Python核心编程2Dive into Python),大致读一次,循环啊判,常用类啊,搞懂(太难的跳过) 2.勤练习py ...

最新文章

  1. 论文被拒,项目被砍?斯坦福最惨在读博士教你如何直面失败
  2. PyTorch 51.BatchNorm和Dropout层的不协调现象
  3. 【数据结构作业心得】纸面6 - Matlab LU分解
  4. 软件工程实践2017 结队项目——第二次作业
  5. 干得累死,并不见得老板就待见你?——来自多位专家的见解
  6. 【新星计划】MATLAB-多项式计算
  7. vscode显示中文乱码问题
  8. ubuntu19.10升级
  9. mac下一些终端命令的使用
  10. weblogic简单介绍
  11. python元组索引_Python—范围元组中的元素索引
  12. javascript this的意思
  13. vcpkg安装_以太坊2.0客户端(Prysm,lighthouse)安装体验
  14. Atitit. 项目文档目录大纲 总集合  v2
  15. 在中国知网下载 PDF 格式的学位论文
  16. sklearn.svm 多分类
  17. ssh登录极路由后台_从浏览器如何进入路由器后台【详细介绍】
  18. support转androidx关系映射
  19. 微软各产品的生命周期
  20. linux如何永久获取root,Linux如何获取root权限?我只想到这些方法了,欢迎补充

热门文章

  1. 目标检测算法(YOLOv4)
  2. 布朗大学的机器人能一笔一划临摹出蒙娜丽莎,还能模仿你的笔迹
  3. “公私结合”打造完整会员营销体系
  4. spark源码分析之ShuffleExternalSorter
  5. 一本通 1216:红与黑
  6. 联想拯救者连不上网?
  7. 使用MD5对用户密码加密与解密
  8. Unity 声音与录音与麦克风实时播放
  9. 我也不知道怎么回事_刚上场说做php的_女嘉宾把灯全灭了,这位程序员哥哥 其实我觊觎你很久了...
  10. 正负数的二进制(转)