开发者

Python+PyQt5实现文件夹结构映射工具

目录
  • 概述
  • 功能亮点
  • 展示效果
  • 软件使用步骤
  • 代码解析
    • 1. 主窗口设计(FolderCopyApp)
    • 2. 拖拽路径输入框(DropLineEdit)
    • 3. 界面布局与控件绑定
    • 4. 复制结构核心逻辑
    • 5. 异常处理和提示
  • 源码下载
    • 总结

      概述

      在日常工作中,我们经常需要对文件夹结构进行复制和备份,比如仅复制一级目录,或者完整复制多级目录,有时还希望连同文件名及后缀创建空文件。手动操作既费时又容易出错。为了解决这个问题,本文将带来一款基于PyQt5开发的「文件夹结构映射工具」,支持拖拽选取路径,三种复制模式,操作简单直观,极大提升工作效率。

      本工具代码精炼,功能实用,界面美观,适合文件管理、项目结构迁移、代码备份等多种场景使用。文章将深入解析程序设计思路、界面布局、功能实现,并附上完整源码下载,方便读者学习和二次开发。

      功能亮点

      路径拖拽与浏览双重选择:支持从资源管理器拖拽文件夹路径到输入框,也可以点击“浏览”按钮选择目录,操作灵活便捷。

      多复制模式支持:

      • 仅复制一级目录结构(不进入子文件夹)
      • 复制多级目录结构(仅文件夹,无文件)
      • 复制多级目录结构并创建空文件(文件名与后缀保持一致)

      路径有效性校验:自动检测源路径和目标路径是否合理,防止错误操作。

      界面简洁美观:采用淡雅配色和流畅交互,按钮及控件布局合理,使用体验良好。

      详细提示反馈:复制完成后弹窗显示创建文件夹数,异常情况及时警告。

      展示效果

      Python+PyQt5实现文件夹结构映射工具

      Python+PyQt5实现文件夹结构映射工具

      • 左侧文本框支持拖拽粘贴目录路径
      • 右侧按钮可弹出系统文件夹选择窗口
      • 中间清晰显示复制模式单选选项
      • 右下角“开始映射结构”按钮启动复制
      • 复制完成弹窗告知成功与否

      软件使用步骤

      1.选择源路径

      可直接拖拽文件夹至左侧输入框,或点击“浏览”按钮弹出选择窗口,选择想复制的文件夹。

      2.选择目标路径

      同样支持拖拽或浏览选择,指定复制结果保存位置。注意目标路径不能是源路径的子目录。

      3.选择复制模式

      • 仅复制一级目录
      • 复制多级目录结构,不含文件
      • 复制多级目录结构并创建空文件
      • 根据需求选择。

      4.点击“开始映射结构”

      程序将按选定模式复制目录结构。完成后弹窗显示操作结果。

      5.查看目标路径

      目标路径将生成对应的目录结构(及空文件),验证复制是否正确。

      代码解析

      1. 主窗口设计(FolderCopyApp)

      继承自QWidget,设置窗口标题、尺寸和基础样式,调用init_ui()方法构建界面。

      self.setWindowTitle(" 文件夹结构映射工具")
      self.setGeometry(300, 300, 600, 350)
      self.setStyleSheet("""
          background-color: #f4f6f9;
          font-family: "Segoe UI";
          font-size:14px;
      """)
      

      2. 拖拽路径输入框(DropLineEdit)

      继承自QLineEdit,重写dragEnterEvent和dropEvent实现路径拖拽识别,提升用户体验。

       def dragEnterEvent(self, e):
          if e.mimeData().hasUrls():
              e.accept()
          else:
              e.ignore()
      
      def dropEvent(self, e):
          if e.mimeData().hasUrls():
              path = e.mimeData().urls()[0].toLocalFile()
              self.setText(path)
      

      3. 界面布局与控件绑定

      使用QvboxLayout整体垂直布局

      每个路径输入区用QHBoxLayout横向放置文本框和浏览按钮

      复制模式通过QGroupBox和QRadioButton呈现,默认选择一级目录复制

      “开始映射结构”按钮绑定复制功能

      self.copy_btn.clicked.connect(self.copy_structure)
      

      4. 复制结构核心逻辑

      copy_structure函数根据模式执行不同目录复制:

      一级目录复制

       or name in os.listdir(source):
          full_path = os.path.join(source, name)
          if os.path.isdir(full_path):
              os.makedirs(os.path.join(target, name), exist_ok=True)
      

      多级目录复制

      for root, dirs, files in os.walk(source):
          rel_path = os.path.relpath(root, source)
          target_dir = os.path.join(target, rel_path)
          os.makedirs(target_dir, exist_ok=True)
      

      - **多级目录复制 + 空文件**

      if mode == "with_files":
          for file in files:
              open(os.path.join(target_dir, file), 'w').close()
      

      5. 异常处理和提示

      校验路径有效性,防止错误操作

      捕获异常,弹窗反馈错误

      复制完成后提示创建目录数量

      源码下载

      import sys
      import os
      from PyQt5.QtWidgets import (
          QApplication, QWidget, QLabel, QLineEdit, QPushButton,
          QVBoxLayout, QHBoxLayout, QFileDialog, QRadioButton,
          QGroupBox, QMessageBox
      )
      from PyQt5.QtCore import Qt
      
      class DropLineEdit(QLineEdit):
          def __init__(self, *args):
              super().__init__(*args)
              self.setAcceptDrops(True)
      
          def dragEnterEvent(self, e):
              if e.mimeData().hasUrls():
                  e.accept()
              else:
                  e.ignore()
      
          def dropEvent(self, e):
              if e.mimeData().hasUrls():
                  path = e.mimeData().urls()[0].toLocalFile()
                  self.setText(path)
      
      class FolderCopyApp(QWidget):
          def __init__(self):
              super().__init__()
              self.setWindowTitle(" 文件夹结构映射工具")
              self.setGeometry(300, 300, 600, 350)
              self.setStyleSheet("""
                  background-color: #f4f6f9;
                  font-family: "Segoe UI";
                  font-size:14px;
              """)
      
              self.init_ui()
      
          def init_ui(self):
              layout = QVBoxLayout()
      
              # 源路径
              source_layout = QHBoxLayout()
              self.source_input = DropLineEdit()
              browse_source = QPushButton("浏览")
              browse_source.setFixedwidth(60)
              browse_source.setStyleSheet(self.button_style())
              browse_source.clicked.connect(self.select_source)
              self.add_field("源路径(拖拽或选择)", self.source_input, browse_source, layout, source_layout)
      
              # 目标路径
              target_layout = QHBoxLayout()
              self.target_input = DropLineEdit()
              browse_target = QPushButton("浏览")
              browse_target.setFixedWidth(60)
              browse_target.setStyleSheet(self.button_style())
              browse_target.clicked.connect(self.select_target)
              self.add_field("目标路径(拖拽或选择)", self.target_input, browse_target, layout, target_layout)
      
              # 模式选择
              self.mode_group = QGroupBox("选择复制模式")
              self.mode_group.setStyleSheet("QGroupBox { font-weight: bold; }")
              mode_layout = QVBoxLayout()
              self.level1_radio = QRadioButton("仅复制一级目录结构")
              self.multilevel_radio = QRadioButton("复制多级目录结构(不含文件)")
              self.with_files_radio = QRadioButton("复制多级结构 + 空文件(保留名称与后缀)")
              self.level1_radio.setChecked(True)
              mode_layout.addWidget(self.level1_radio)
              mode_layout.addWidget(self.multilevel_radio)
              mode_layout.addWidget(self.with_files_radio)
              self.mode_group.setLayout(mode_layout)
              layout.addWidget(self.mode_group)
      
              # 操作按钮
              self.copy_btn = QPushButton(" 开始映射结构")
              self.copy_btn.setStyleSheet(self.button_style())
              self.copy_btn.clicked.connect(self.copy_structure)
              layout.addWidget(self.copy_btn)
      
              self.setLayout(layout)
      
          def add_field(self, label_text, line_edit, button, layout, sublayout):
              label = QLabel(label_text)
              label.setStyleSheet("color: #333;")
              layout.addWidget(label)
              sublayout.addWidget(line_edit)
              sublayout.addWidget(button)
              layout.addLayout(sublayout)
      
          def button_style(self):
              return """
                  QPushButton {
                      background-color: #5c9ded;
                      color: white;
                      border: none;
                      padding: 6px 12px;
               js       border-radius: 4px;
                      font-family: "Segoe UI", "Roboto", "Helvetica Neue", Arial, sans-serif;
                      font-weight: bold;
                  }
                  QPushButton:hover {
                      background-color: #468be6;
                  }
              """
      
          def select_source(self):
              path = QFileDialog.getExistingDirectory(self, js"选择源目录")
              if path:
                  self.source_input.setText(path)
      
          def select_target(self):
              path = QFileDialog.getExistingDirectory(self, "选择目标目录")
              if path:
                  self.target_input.setText(path)
      
          def copy_structure(self):
              source = self.souphprce_input.text().strip()
              target = self.target_input.text().strip()
              mode = "level1" if self.level1_radio.isChecked() else \
                     "multilevel" if self.multilevel_radio.isChecked() else "with_files"
      
              if not source or not target:
                  QMessageBo编程x.warning(self, "错误", "请设置源路径和目标路径")
                  return
      
              if not os.path.exists(source):
                  QMessageBox.warning(self, "错误", "源路径无效")
                  return
      
              if os.path.commonpath([source]) == os.path.commonpath([source, target]):
                  QMessageBox.warning(self, "错误", "目标路径不能位于源路径内部")
                  return
      
              try:
                  created = 0
      
                  if mode == "level1":
                      # 仅复制一级目录结构(直接子文件夹)
                      for name in os.listdir(source):
                          full_path = os.path.join(source, name)
                          if os.path.isdir(full_path):
                              os.makedirs(os.path.join(target, name), exist_ok=True)
                              created += 1
                  else:
                      for root, dirs, files in os.walk(source):
                          rel_path = os.path.relpath(root, source)
                          target_dir = os.path.join(target, rel_path)
                          os.makedirs(target_dir, exist_ok=True)
                          created += 1
      
                          if mode == "with_files":
                              for file in files:
                                  try:
                                      open(os.path.join(target_dir, file), 'w').close()
                                  except Exception as fe:
                                      print(f"无法创建文件:{file}, 错误:{fe}")
      
               编程客栈   QMessageBox.information(self, "完成", f"结构复制完成,创建文件夹数:{created}")
              except Exception as e:
                  QMessageBox.critical(self, "错误", str(e))
      
      if __name__ == "__main__":
          app = QApplication(sys.argv)
          window = FolderCopyApp()
          window.show()
          sys.exit(app.exec_())
      

      总结

      这款基于PyQt5的「文件夹结构映射工具」功能实用,代码清晰,界面友好,适合所有需要目录结构复制的场景。通过拖拽输入和多复制模式满足不同用户需求。本文不仅介绍了工具功能,还详细剖析了关键代码和实现细节。希望对您学习PyQt5 GUI开发、文件系统操作提供有价值的参考。

      到此这篇关于python+PyQt5实现文件夹结构映射工具的文章就介绍到这了,更多相关Python文件夹结构映射内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!

      0

      上一篇:

      下一篇:

      精彩评论

      暂无评论...
      验证码 换一张
      取 消

      最新开发

      开发排行榜