当前位置: 首页 > article >正文

PyQt5实战:用QTreeView+QStandardItemModel快速构建你的第一个树形文件浏览器(附完整代码)

PyQt5实战用QTreeViewQStandardItemModel快速构建你的第一个树形文件浏览器每次看到电脑资源管理器左侧那整齐的目录树你是否好奇过它是如何实现的今天我们就用PyQt5的QTreeView和QStandardItemModel组件从零开始打造一个简易但功能完整的树形文件浏览器。这个项目不仅能让你快速掌握PyQt5中树形视图的核心用法还能获得一个可以直接集成到更大项目中的实用组件。1. 环境准备与基础概念在开始编码前我们需要确保开发环境配置正确。建议使用Python 3.6和最新版PyQt5pip install pyqt5QTreeView是PyQt5中用于显示层级数据的强大组件而QStandardItemModel则是与之配套的标准数据模型。它们的关系就像书架和书籍QTreeView负责数据的可视化展示和用户交互QStandardItemModel负责数据的存储和组织QStandardItem模型中的基本数据单元可以包含文本、图标等多种数据这种MVC模型-视图-控制器架构让数据管理和界面展示分离是GUI开发的黄金法则。下面是一个最简单的QTreeView示例from PyQt5.QtWidgets import QApplication, QTreeView from PyQt5.QtGui import QStandardItemModel, QStandardItem app QApplication([]) # 创建模型和视图 model QStandardItemModel() tree QTreeView() tree.setModel(model) # 添加示例数据 root_item QStandardItem(根节点) model.appendRow(root_item) child_item QStandardItem(子节点) root_item.appendRow(child_item) tree.show() app.exec_()运行这段代码你会看到一个包含两级节点的简单树形结构。接下来我们将基于这个基础构建更实用的文件浏览器。2. 构建文件浏览器框架真正的文件浏览器需要动态加载目录结构。我们先创建主窗口类并添加必要的组件import os from PyQt5.QtWidgets import (QMainWindow, QFileIconProvider, QWidget, QVBoxLayout) from PyQt5.QtGui import QStandardItemModel, QStandardItem class FileBrowser(QMainWindow): def __init__(self): super().__init__() self.setWindowTitle(PyQt5文件浏览器) self.resize(800, 600) # 中央组件 central_widget QWidget() self.setCentralWidget(central_widget) # 主布局 layout QVBoxLayout() central_widget.setLayout(layout) # 创建树形视图和模型 self.tree_view QTreeView() self.model QStandardItemModel() self.tree_view.setModel(self.model) layout.addWidget(self.tree_view) # 设置初始目录 self.populate_tree(os.path.expanduser(~)) # 从用户主目录开始这里的关键是populate_tree方法它负责加载指定路径下的文件和文件夹。我们先实现一个基础版本def populate_tree(self, path): self.model.clear() self.model.setHorizontalHeaderLabels([名称]) root_item QStandardItem(path) self.model.appendRow(root_item) for item_name in os.listdir(path): item_path os.path.join(path, item_name) item QStandardItem(item_name) if os.path.isdir(item_path): # 为目录添加一个空的子项以便显示展开箭头 dummy_item QStandardItem() item.appendRow(dummy_item) root_item.appendRow(item)这个初步实现已经可以显示目录结构但存在几个明显问题没有区分文件和文件夹的图标子目录需要点击展开后才能加载内容性能未经优化大目录会卡顿3. 添加图标和懒加载让文件浏览器更专业的第一步是添加适当的图标。PyQt5提供了QFileIconProvider来获取系统标准图标from PyQt5.QtWidgets import QFileIconProvider class FileBrowser(QMainWindow): def __init__(self): # ...之前的初始化代码... self.icon_provider QFileIconProvider() def populate_tree(self, path, parent_itemNone): if parent_item is None: # 根目录 self.model.clear() self.model.setHorizontalHeaderLabels([名称, 类型, 大小]) parent_item QStandardItem(self.icon_provider.icon(QFileIconProvider.Folder), os.path.basename(path)) self.model.appendRow(parent_item) else: parent_item.removeRow(0) # 移除dummy item for item_name in sorted(os.listdir(path)): item_path os.path.join(path, item_name) if os.path.isdir(item_path): item QStandardItem(self.icon_provider.icon(QFileIconProvider.Folder), item_name) # 添加dummy item以实现懒加载 dummy_item QStandardItem() item.appendRow(dummy_item) else: item QStandardItem(self.icon_provider.icon(QFileIconProvider.File), item_name) parent_item.appendRow(item)要实现懒加载即只在需要时加载子目录我们需要连接QTreeView的expanded信号self.tree_view.expanded.connect(self.on_item_expanded) def on_item_expanded(self, index): item self.model.itemFromIndex(index) if item.rowCount() 1 and not self.model.item(item.row(), 0, item.index()).text(): path self.get_full_path(item) self.populate_tree(path, item) def get_full_path(self, item): path [] while item is not None: path.append(item.text()) item item.parent() return os.path.join(*reversed(path))现在我们的文件浏览器已经具备了基本功能但还可以进一步优化。4. 性能优化与额外功能当处理包含大量文件的目录时直接加载所有项目会导致界面卡顿。我们可以采用以下优化策略分块加载初次只加载前N个项目滚动到底部时再加载更多def populate_tree(self, path, parent_itemNone, limit500): # ...之前的代码... items sorted(os.listdir(path)) if len(items) limit: items items[:limit] # 添加加载更多项 more_item QStandardItem(... (点击加载更多)) parent_item.appendRow(more_item)后台加载使用QThread在后台扫描目录避免阻塞主线程from PyQt5.QtCore import QThread, pyqtSignal class DirectoryScanner(QThread): scan_finished pyqtSignal(list) def __init__(self, path): super().__init__() self.path path def run(self): try: items sorted(os.listdir(self.path)) self.scan_finished.emit(items) except Exception as e: print(f扫描错误: {e}) self.scan_finished.emit([])在FileBrowser类中使用这个工作线程def populate_tree(self, path, parent_itemNone): if parent_item is None: # ...根目录处理... else: self.scanner DirectoryScanner(path) self.scanner.scan_finished.connect( lambda items: self.update_tree(items, path, parent_item)) self.scanner.start() def update_tree(self, items, path, parent_item): parent_item.removeRow(0) # 移除dummy item for item_name in items: # ...添加项目的代码...添加文件信息列显示文件类型和大小from PyQt5.QtCore import QFileInfo def update_tree(self, items, path, parent_item): # ...之前的代码... for item_name in items: item_path os.path.join(path, item_name) file_info QFileInfo(item_path) if os.path.isdir(item_path): item QStandardItem(self.icon_provider.icon(QFileIconProvider.Folder), item_name) # 添加dummy item dummy_item QStandardItem() item.appendRow(dummy_item) type_item QStandardItem(文件夹) size_item QStandardItem() else: item QStandardItem(self.icon_provider.icon(QFileIconProvider.File), item_name) type_item QStandardItem(file_info.suffix().upper() 文件) size_item QStandardItem(self.format_size(file_info.size())) parent_item.appendRow([item, type_item, size_item]) def format_size(self, size): for unit in [B, KB, MB, GB]: if size 1024: return f{size:.1f} {unit} size / 1024 return f{size:.1f} TB5. 完整实现与进阶扩展将以上所有部分组合起来我们就得到了一个功能完整的文件浏览器。以下是完整的代码结构import os from PyQt5.QtWidgets import (QMainWindow, QTreeView, QFileIconProvider, QWidget, QVBoxLayout) from PyQt5.QtGui import QStandardItemModel, QStandardItem from PyQt5.QtCore import QFileInfo, QThread, pyqtSignal class DirectoryScanner(QThread): # ...如前所述... class FileBrowser(QMainWindow): def __init__(self): # ...初始化代码... def populate_tree(self, path, parent_itemNone): # ...目录加载代码... def on_item_expanded(self, index): # ...处理展开事件的代码... def update_tree(self, items, path, parent_item): # ...更新树形视图的代码... def get_full_path(self, item): # ...获取完整路径的代码... def format_size(self, size): # ...格式化文件大小的代码... if __name__ __main__: import sys from PyQt5.QtWidgets import QApplication app QApplication(sys.argv) browser FileBrowser() browser.show() sys.exit(app.exec_())这个文件浏览器还可以进一步扩展添加右键菜单实现文件操作如重命名、删除等实现文件预览在右侧面板显示选中文件的内容添加书签功能快速访问常用目录支持搜索过滤实时过滤显示的文件例如添加右键菜单可以这样实现from PyQt5.QtWidgets import QMenu class FileBrowser(QMainWindow): def __init__(self): # ...之前的代码... self.tree_view.setContextMenuPolicy(Qt.CustomContextMenu) self.tree_view.customContextMenuRequested.connect(self.show_context_menu) def show_context_menu(self, position): index self.tree_view.indexAt(position) if not index.isValid(): return menu QMenu() open_action menu.addAction(打开) rename_action menu.addAction(重命名) delete_action menu.addAction(删除) action menu.exec_(self.tree_view.viewport().mapToGlobal(position)) if action open_action: self.open_file(index) elif action rename_action: self.rename_file(index) elif action delete_action: self.delete_file(index) def open_file(self, index): path self.get_full_path(self.model.itemFromIndex(index)) if os.path.isfile(path): os.startfile(path) # Windows # 其他平台可使用subprocess或QDesktopServices通过这个项目我们不仅学会了QTreeView和QStandardItemModel的基本用法还掌握了PyQt5中几个重要概念模型/视图架构自定义数据模型懒加载技术后台线程处理上下文菜单这些技术可以应用于各种GUI开发场景如邮件客户端、项目管理工具等任何需要展示层级数据的应用程序。

相关文章:

PyQt5实战:用QTreeView+QStandardItemModel快速构建你的第一个树形文件浏览器(附完整代码)

PyQt5实战:用QTreeViewQStandardItemModel快速构建你的第一个树形文件浏览器 每次看到电脑资源管理器左侧那整齐的目录树,你是否好奇过它是如何实现的?今天我们就用PyQt5的QTreeView和QStandardItemModel组件,从零开始打造一个简…...

拆解Lite-HRNet的‘轻量’魔法:ShuffleBlock与CCWBlock如何省下80%算力

拆解Lite-HRNet的‘轻量’魔法:ShuffleBlock与CCWBlock如何省下80%算力 在计算机视觉领域,高分辨率网络(HRNet)因其出色的特征保持能力而备受推崇,但随之而来的计算成本却让许多实际应用望而却步。Lite-HRNet的出现&a…...

三步打造清爽Mac菜单栏:Dozer终极隐藏方案

三步打造清爽Mac菜单栏:Dozer终极隐藏方案 【免费下载链接】Dozer Hide menu bar icons on macOS 项目地址: https://gitcode.com/gh_mirrors/do/Dozer 还在为Mac菜单栏上拥挤不堪的图标感到困扰吗?想要一个简洁高效的工作界面?Dozer正…...

告别窗口拖拽:用Loop实现Mac高效分屏的5个核心技巧

告别窗口拖拽:用Loop实现Mac高效分屏的5个核心技巧 【免费下载链接】Loop MacOS窗口管理 项目地址: https://gitcode.com/GitHub_Trending/lo/Loop 每天在Mac上工作时,你是否经常被这些问题困扰:窗口太多找不到想要的那个?…...

Obsidian Copilot 深度解析:构建知识管理中的智能代理系统

Obsidian Copilot 深度解析:构建知识管理中的智能代理系统 【免费下载链接】obsidian-copilot A ChatGPT Copilot in Obsidian 项目地址: https://gitcode.com/gh_mirrors/ob/obsidian-copilot 在知识管理工具日益同质化的今天,Obsidian Copilot …...

基于OpenCV的多条形码高效定位与识别实战

1. 为什么需要多条形码识别技术 在零售仓储和物流分拣场景中,我们经常需要同时处理多个条形码。比如快递站点的包裹分拣机,每秒钟要处理数十个包裹的条形码;超市收银台的商品堆里,经常叠放着五六件带条形码的商品。传统扫码枪需要…...

Windows风扇噪音终结者:FanControl实战解密与深度配置

Windows风扇噪音终结者:FanControl实战解密与深度配置 【免费下载链接】FanControl.Releases This is the release repository for Fan Control, a highly customizable fan controlling software for Windows. 项目地址: https://gitcode.com/GitHub_Trending/fa…...

C++ vcpkg:安装、使用、原理与选型

C vcpkg:安装、使用、原理与选型 vcpkg 是微软与社区维护的开源 C/C 包管理器,目标是统一第三方库的获取、构建与集成流程。它支持 Windows / Linux / macOS,并与 CMake、Visual Studio 等工具链深度协作。本文覆盖:是什么、如何…...

Downr1n iOS降级与越狱实战指南:从问题诊断到解决方案

Downr1n iOS降级与越狱实战指南:从问题诊断到解决方案 【免费下载链接】downr1n downgrade tethered checkm8 idevices ios 14, 15. 项目地址: https://gitcode.com/gh_mirrors/do/downr1n 一、决策指南:为什么选择Downr1n? 1.1 核心…...

RexUniNLU硬件加速:TensorRT推理优化实践

RexUniNLU硬件加速:TensorRT推理优化实践 想让你的RexUniNLU模型推理速度飞起来吗?尤其是在T4这类消费级显卡上,看着模型慢悠悠地吐出结果,是不是有点着急?今天咱们就来聊聊怎么用TensorRT给RexUniNLU“打一针强心剂”…...

LeetCode 70. Climbing Stairs 题解

LeetCode 70. Climbing Stairs 题解 题目描述 假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n 2 输出:2 解释:有两种方法可以爬到楼…...

深度学习项目训练环境多场景落地:自动驾驶小车图像识别项目快速启动

深度学习项目训练环境多场景落地:自动驾驶小车图像识别项目快速启动 你是不是也遇到过这样的问题?想跑一个深度学习项目,光是配环境就花了大半天,各种版本冲突、依赖报错,好不容易装好了,一运行又提示缺这…...

别再裸奔你的实时数据流了!用Python+Starlette给SSE接口加个Header认证门卫

实时数据流安全加固:PythonStarlette实现SSE接口的Bearer Token认证 想象一下,你精心构建的实时数据看板突然被不明身份的用户随意访问,敏感的业务指标像超市促销传单一样被任意获取——这不是危言耸听,而是许多开发者在使用SSE技…...

CDAN不只是论文里的公式:深入浅出图解‘条件对抗’如何让领域自适应更精准

CDAN不只是论文里的公式:深入浅出图解‘条件对抗’如何让领域自适应更精准 想象你是一位冰淇淋品鉴师,需要将一家老牌店铺(源域)的配方迁移到新店铺(目标域)。传统方法粗暴混合所有原料,导致巧…...

VSCode远程开发终极指南:5分钟搞定跳板机+服务器免密配置(附SSH密钥生成教程)

VSCode远程开发终极指南:5分钟搞定跳板机服务器免密配置 每次连接远程服务器都要输入密码、反复跳转终端,是不是已经让你精疲力尽?作为开发者,我们值得拥有更优雅的远程开发体验。今天要分享的这套方案,不仅能让你在VS…...

避坑指南:STM32磁编码器校准常见的5个错误及解决方案

STM32磁编码器校准实战:5个典型错误分析与高阶解决方案 磁编码器在步进电机控制系统中扮演着关键角色,而MT6816作为国产AMR技术代表芯片,其14位高精度输出为位置检测提供了可靠保障。但在实际校准过程中,开发者常会遇到CALI_Error…...

深入解析:set_clock_groups中-physically_exclusive与-asynchronous的约束协同与必要性

1. 从Spyglass报错看时钟约束的必要性 最近在跑Spyglass做SDC检查时,遇到了一个让我困惑的报错:"当两个时钟设置成物理互斥或逻辑互斥时,需要另外加上这两个时钟是异步设置的约束"。这让我很纳闷,明明已经设置了物理互…...

Altium Designer新手必看:5分钟搞定PCB封装库创建(附3D模型导入技巧)

Altium Designer新手实战:从零构建PCB封装库与3D模型高效导入 刚接触Altium Designer的工程师常被PCB封装库的创建难住——焊盘尺寸怎么定?丝印如何对齐?3D模型能否可视化验证?这些问题直接关系到后期PCB设计的成功率。本文将用最…...

OpenSSL实战:手把手教你创建自签名根证书

1. 为什么需要自签名根证书? 想象一下你正在搭建一个内部测试环境,或者为公司的内部系统建立一套专属的安全通信机制。这时候你会发现,所有涉及HTTPS的环节都需要SSL/TLS证书。如果直接购买商业CA颁发的证书,不仅成本高&#xff…...

交换机堆灰指南:为什么你的HSRP热备切换总超15秒?从生成树到接口追踪的完整排错

交换机堆灰指南:为什么你的HSRP热备切换总超15秒?从生成树到接口追踪的完整排错 当核心交换机的HSRP切换时间超过15秒,业务中断的每一毫秒都在考验运维团队的神经。这不是简单的协议超时问题,而是网络冗余架构中多个子系统协同失效…...

Llama-3.2V-11B-cot实操手册:构建带反馈机制的迭代式视觉推理Agent

Llama-3.2V-11B-cot实操手册:构建带反馈机制的迭代式视觉推理Agent 你有没有遇到过这种情况?给AI看一张复杂的图表或流程图,它要么答非所问,要么只能给出一个笼统的、没有逻辑链条的答案。你心里想:“它到底是怎么得出…...

OpenClaw夜间任务优化:Qwen3-32B+RTX4090D镜像低负载模式配置

OpenClaw夜间任务优化:Qwen3-32BRTX4090D镜像低负载模式配置 1. 问题背景与优化动机 去年12月,我开始用OpenClawQwen3-32B模型搭建个人自动化工作流。最初配置的定时备份任务每晚11点准时运行,但很快发现两个问题: 电费异常&am…...

APKMirror客户端:安卓应用安全下载与管理的革新方案

APKMirror客户端:安卓应用安全下载与管理的革新方案 【免费下载链接】APKMirror 项目地址: https://gitcode.com/gh_mirrors/ap/APKMirror 在安卓应用获取的过程中,用户常常面临两难选择:官方应用商店的更新滞后与第三方平台的安全隐…...

Nunchaku-flux-1-dev技术解析:深入理解其背后的深度学习网络架构

Nunchaku-flux-1-dev技术解析:深入理解其背后的深度学习网络架构 最近在AI编程和图像生成圈子里,FLUX.1 [dev]这个名字被讨论得越来越多。作为其社区衍生版本,Nunchaku-flux-1-dev自然也吸引了大量技术爱好者的目光。大家可能已经体验过它生…...

PP-DocLayoutV3入门必看:从零部署到JSON结构化输出完整流程

PP-DocLayoutV3入门必看:从零部署到JSON结构化输出完整流程 1. 开篇:认识文档布局分析利器 你是否曾经遇到过这样的困扰:面对扫描的文档图片,想要提取其中的文字和结构信息,却不知道从何下手?或者需要处理…...

Apollo自动驾驶系统C++核心模块实战解析——从源码到实现

1. Apollo自动驾驶系统架构全景解析 第一次打开Apollo源码仓库时,我完全被它庞大的代码量震撼到了——超过200万行C代码构成的自动驾驶系统,就像一座精密的机械钟表。但当你拆解它的核心模块后,会发现其架构设计处处体现着模块化和高内聚低耦…...

Xinference+tao-8k实战:快速构建文档相似度分析工具

Xinferencetao-8k实战:快速构建文档相似度分析工具 1. 从想法到工具:为什么你需要一个文档相似度分析器 想象一下这个场景:你手头有几百份技术文档、产品说明或者客户反馈,你想快速找出哪些文档在讨论同一个主题,或者…...

Wan2.2-I2V-A14B生产环境部署:Nginx反向代理与Docker Compose编排

Wan2.2-I2V-A14B生产环境部署:Nginx反向代理与Docker Compose编排 1. 部署目标与前置准备 在开始之前,我们先明确这次部署要实现的目标:通过Docker Compose编排Wan2.2-I2V-A14B模型服务及其依赖组件,使用Nginx作为反向代理&…...

高效音频获取与资源管理:喜马拉雅下载工具全解析

高效音频获取与资源管理:喜马拉雅下载工具全解析 【免费下载链接】xmly-downloader-qt5 喜马拉雅FM专辑下载器. 支持VIP与付费专辑. 使用GoQt5编写(Not Qt Binding). 项目地址: https://gitcode.com/gh_mirrors/xm/xmly-downloader-qt5 在数字内容消费时代&a…...

Blender3mfFormat全链路应用指南:从基础操作到专业级工作流构建

Blender3mfFormat全链路应用指南:从基础操作到专业级工作流构建 【免费下载链接】Blender3mfFormat Blender add-on to import/export 3MF files 项目地址: https://gitcode.com/gh_mirrors/bl/Blender3mfFormat 基础认知:3MF格式与Blender插件体…...