使用 Python创建照片文件复制和压缩工具

在这篇博客中,我们将探索如何使用 wxPython 创建一个 GUI 工具,用于选择文件夹中的照片文件、显示预览、选择并复制文件到指定目录,以及将选中的照片压缩到一个 ZIP 文件中。这个工具不仅功能强大,而且提供了用户友好的界面。
C:\pythoncode\new\photofilecopyandzip.py

全部代码

import wx
import os
from datetime import datetime
import shutil
import zipfileclass MyFrame(wx.Frame):def __init__(self, *args, **kwargs):super(MyFrame, self).__init__(*args, **kwargs)self.panel = wx.Panel(self)self.vbox = wx.BoxSizer(wx.VERTICAL)self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)self.openBtn = wx.Button(self.panel, label='Open Folder')self.selectAllBtn = wx.Button(self.panel, label='Select All')self.deselectAllBtn = wx.Button(self.panel, label='Deselect All')self.copyBtn = wx.Button(self.panel, label='Copy')self.compressBtn = wx.Button(self.panel, label='Compress')self.hbox1.Add(self.openBtn)self.hbox1.Add(self.selectAllBtn)self.hbox1.Add(self.deselectAllBtn)self.hbox1.Add(self.copyBtn)self.hbox1.Add(self.compressBtn)self.splitter = wx.SplitterWindow(self.panel)self.listView = wx.ListCtrl(self.splitter, style=wx.LC_REPORT | wx.BORDER_SUNKEN)self.listView.InsertColumn(0, 'Image Files')self.listView.InsertColumn(1, 'Size')self.listView.InsertColumn(2, 'Dimensions')self.listView.InsertColumn(3, 'Date')self.imagePreview = wx.StaticBitmap(self.splitter)self.splitter.SplitVertically(self.listView, self.imagePreview)self.splitter.SetSashGravity(0.5)self.vbox.Add(self.hbox1, 0, wx.EXPAND | wx.ALL, 5)self.vbox.Add(self.splitter, 1, wx.EXPAND)self.panel.SetSizer(self.vbox)self.Bind(wx.EVT_BUTTON, self.on_open_folder, self.openBtn)self.Bind(wx.EVT_BUTTON, self.on_select_all, self.selectAllBtn)self.Bind(wx.EVT_BUTTON, self.on_deselect_all, self.deselectAllBtn)self.Bind(wx.EVT_BUTTON, self.on_copy_photos, self.copyBtn)self.Bind(wx.EVT_BUTTON, self.on_compress_photos, self.compressBtn)self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_item_selected, self.listView)self.image_paths = {}self.selected_images = []def on_open_folder(self, event):with wx.DirDialog(self, "Choose a directory") as dlg:if dlg.ShowModal() == wx.ID_OK:folder_path = dlg.GetPath()self.load_images(folder_path)def load_images(self, folder_path):self.listView.DeleteAllItems()img_files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]items = []  # 存储将要插入的项信息for img_file in img_files:img_path = os.path.join(folder_path, img_file)img = wx.Image(img_path, wx.BITMAP_TYPE_ANY)if img.IsOk():size = os.path.getsize(img_path)dimensions = f"{img.GetWidth()}x{img.GetHeight()}"date = datetime.fromtimestamp(os.path.getmtime(img_path)).strftime('%Y-%m-%d %H:%M:%S')items.append((img_file, size, dimensions, date, img_path))# 批量插入项for index, (file_name, size, dimensions, date, img_path) in enumerate(items):item_index = self.listView.InsertItem(index, file_name)if item_index != -1:self.listView.SetItem(item_index, 1, f"{size} bytes")self.listView.SetItem(item_index, 2, dimensions)self.listView.SetItem(item_index, 3, date)self.image_paths[item_index] = img_pathself.listView.SetItem(item_index, 2, dimensions)self.listView.SetItem(item_index, 3, date)self.image_paths[item_index] = img_pathdef on_item_selected(self, event):self.show_image_preview(event.GetIndex())def show_image_preview(self, index):img_path = self.image_paths.get(index)if img_path and os.path.exists(img_path):img = wx.Image(img_path, wx.BITMAP_TYPE_ANY)if img.IsOk():W = img.GetWidth()H = img.GetHeight()NewW = int(W / 2)NewH = int(H / 2)img = img.Scale(NewW, NewH)self.imagePreview.SetBitmap(wx.Bitmap(img))self.imagePreview.Refresh()def on_select_all(self, event):item_count = self.listView.GetItemCount()for index in range(item_count):self.listView.Select(index)def on_deselect_all(self, event):item_count = self.listView.GetItemCount()for index in range(item_count):self.listView.Select(index, on=0)def on_copy_photos(self, event):with wx.DirDialog(self, "Choose a destination directory") as dlg:if dlg.ShowModal() == wx.ID_OK:dest_folder = dlg.GetPath()selected_items = [self.image_paths[index] for index in range(self.listView.GetItemCount()) if self.listView.IsSelected(index)]for img_path in selected_items:shutil.copy(img_path, dest_folder)def on_compress_photos(self, event):selected_items = [self.image_paths[index] for index in range(self.listView.GetItemCount()) if self.listView.IsSelected(index)]if selected_items:now = datetime.now().strftime("_%Y%m%d%H%M%S")folder_name = os.path.basename(os.path.dirname(selected_items[0])) + nowzip_filename = f"{folder_name}.zip"with zipfile.ZipFile(zip_filename, 'w') as zipf:for img_path in selected_items:zipf.write(img_path, os.path.basename(img_path))if __name__ == "__main__":app = wx.App(False)frame = MyFrame(None, title="Photo File Copy and Zip")frame.Show()app.MainLoop()

步骤 1:设置开发环境

首先,我们需要安装 wxPython。如果还没有安装,可以通过以下命令安装:

pip install wxPython

步骤 2:创建 GUI 界面

我们将从创建一个简单的 GUI 界面开始。界面包括按钮、列表视图和图片预览窗口。

import wx
import os
from datetime import datetime
import shutil
import zipfileclass MyFrame(wx.Frame):def __init__(self, *args, **kwargs):super(MyFrame, self).__init__(*args, **kwargs)self.panel = wx.Panel(self)self.vbox = wx.BoxSizer(wx.VERTICAL)self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)self.openBtn = wx.Button(self.panel, label='Open Folder')self.selectAllBtn = wx.Button(self.panel, label='Select All')self.deselectAllBtn = wx.Button(self.panel, label='Deselect All')self.copyBtn = wx.Button(self.panel, label='Copy')self.compressBtn = wx.Button(self.panel, label='Compress')self.hbox1.Add(self.openBtn)self.hbox1.Add(self.selectAllBtn)self.hbox1.Add(self.deselectAllBtn)self.hbox1.Add(self.copyBtn)self.hbox1.Add(self.compressBtn)self.splitter = wx.SplitterWindow(self.panel)self.listView = wx.ListCtrl(self.splitter, style=wx.LC_REPORT | wx.BORDER_SUNKEN)self.listView.InsertColumn(0, 'Image Files')self.listView.InsertColumn(1, 'Size')self.listView.InsertColumn(2, 'Dimensions')self.listView.InsertColumn(3, 'Date')self.imagePreview = wx.StaticBitmap(self.splitter)self.splitter.SplitVertically(self.listView, self.imagePreview)self.splitter.SetSashGravity(0.5)self.vbox.Add(self.hbox1, 0, wx.EXPAND | wx.ALL, 5)self.vbox.Add(self.splitter, 1, wx.EXPAND)self.panel.SetSizer(self.vbox)self.Bind(wx.EVT_BUTTON, self.on_open_folder, self.openBtn)self.Bind(wx.EVT_BUTTON, self.on_select_all, self.selectAllBtn)self.Bind(wx.EVT_BUTTON, self.on_deselect_all, self.deselectAllBtn)self.Bind(wx.EVT_BUTTON, self.on_copy_photos, self.copyBtn)self.Bind(wx.EVT_BUTTON, self.on_compress_photos, self.compressBtn)self.Bind(wx.EVT_LIST_ITEM_SELECTED, self.on_item_selected, self.listView)self.image_paths = {}self.selected_images = []def on_open_folder(self, event):with wx.DirDialog(self, "Choose a directory") as dlg:if dlg.ShowModal() == wx.ID_OK:folder_path = dlg.GetPath()self.load_images(folder_path)def load_images(self, folder_path):self.listView.DeleteAllItems()img_files = [f for f in os.listdir(folder_path) if os.path.isfile(os.path.join(folder_path, f))]for index, img_file in enumerate(img_files):img_path = os.path.join(folder_path, img_file)img = wx.Image(img_path, wx.BITMAP_TYPE_ANY)if img.IsOk():size = os.path.getsize(img_path)dimensions = f"{img.GetWidth()}x{img.GetHeight()}"date = datetime.fromtimestamp(os.path.getmtime(img_path)).strftime('%Y-%m-%d %H:%M:%S')item_index = self.listView.InsertItem(index, img_file)if item_index != -1:self.listView.SetItem(item_index, 1, f"{size} bytes")self.listView.SetItem(item_index, 2, dimensions)self.listView.SetItem(item_index, 3, date)self.image_paths[item_index] = img_pathdef on_item_selected(self, event):self.show_image_preview(event.GetIndex())def show_image_preview(self, index):img_path = self.image_paths.get(index)if img_path and os.path.exists(img_path):img = wx.Image(img_path, wx.BITMAP_TYPE_ANY)if img.IsOk():W = img.GetWidth()H = img.GetHeight()NewW = int(W / 2)NewH = int(H / 2)img = img.Scale(NewW, NewH)self.imagePreview.SetBitmap(wx.Bitmap(img))self.imagePreview.Refresh()def on_select_all(self, event):item_count = self.listView.GetItemCount()for index in range(item_count):self.listView.Select(index)def on_deselect_all(self, event):item_count = self.listView.GetItemCount()for index in range(item_count):self.listView.Select(index, on=0)def on_copy_photos(self, event):with wx.DirDialog(self, "Choose a destination directory") as dlg:if dlg.ShowModal() == wx.ID_OK:dest_folder = dlg.GetPath()selected_items = [self.image_paths[index] for index in range(self.listView.GetItemCount()) if self.listView.IsSelected(index)]for img_path in selected_items:shutil.copy(img_path, dest_folder)def on_compress_photos(self, event):selected_items = [self.image_paths[index] for index in range(self.listView.GetItemCount()) if self.listView.IsSelected(index)]if selected_items:now = datetime.now().strftime("_%Y%m%d%H%M%S")folder_name = os.path.basename(os.path.dirname(selected_items[0])) + nowzip_filename = f"{folder_name}.zip"with zipfile.ZipFile(zip_filename, 'w') as zipf:for img_path in selected_items:zipf.write(img_path, os.path.basename(img_path))if __name__ == "__main__":app = wx.App(False)frame = MyFrame(None, title="Photo File Copy and Zip")frame.Show()app.MainLoop()

步骤 3:运行和测试

保存上述代码到一个文件(例如 photofilecopyandzip.py),然后在命令行运行:

python photofilecopyandzip.py

你将看到一个 GUI 窗口,其中包含各种按钮和一个列表视图。点击“Open Folder”按钮选择包含照片的文件夹,照片文件将显示在列表视图中。你可以选择全部或部分照片,然后选择复制到另一个文件夹或者压缩为 ZIP 文件。

关键功能解析

  1. 打开文件夹
    使用 wx.DirDialog 打开文件夹对话框,选择包含照片的文件夹。通过 os.listdir 获取文件夹中的文件列表,并使用 wx.Image 加载并显示图片。

  2. 显示图片预览
    当用户选择列表中的图片时,使用 wx.StaticBitmap 显示图片的缩略图。

  3. 选择和取消选择
    提供全选和取消选择按钮,便于用户批量选择和取消选择照片文件。

  4. 复制照片
    通过 shutil.copy 将选中的照片文件复制到指定目录。

  5. 压缩照片
    使用 zipfile.ZipFile 创建 ZIP 文件,将选中的照片文件添加到 ZIP 文件中。

结果如下

在这里插入图片描述

结论

通过这篇博客,我们创建了一个功能全面的照片文件管理工具,能够帮助用户方便地选择、预览、复制和压缩照片文件。这个工具展示了 wxPython 在创建桌面应用程序时的强大功能和灵活性。希望你能从中学到有用的知识,并将其应用到你自己的项目中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/384076.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

3.多租户调研1

https://gitee.com/xiaoqiangBUG/hello-ruoyi-cloud.git 1.mybatis plus 的插件 TenantLineInnerInterceptor 是 MyBatis Plus 框架中的一个拦截器,它用于实现多租户系统的数据隔离。在多租户应用中,不同的租户应该只能访问到自己的数据,而…

时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法(CPO)优化VMD二次分解

时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法(CPO)优化VMD二次分解 目录 时序分解 | Matlab基于CEEMDAN-CPO-VMD的CEEMDAN结合冠豪猪优化算法(CPO)优化VMD二次分解效果一览基本介绍程序设计参考资料 效果一览…

数据结构经典测试题4

1. #include <stdio.h> int main() { char *str[3] {"stra", "strb", "strc"}; char *p str[0]; int i 0; while(i < 3) { printf("%s ",p); i; } return 0; }上述代码运行结果是什么&#xff1f; A: stra strb strc B: s…

RFID温度标签: 冷链管理迈向智能化、精准化的新时代。

在现代商业和社会发展中&#xff0c;冷链物流扮演着至关重要的角色。它不仅涉及食品、药品等敏感物资的安全运输&#xff0c;更是保障公众健康与福祉的重要环节。随着人们对生鲜冷链需求的日益增长&#xff0c;冷链物流行业也迎来了以物联网技术为主导发展新阶段。我国冷链物流…

嵌入式中什么是三次握手

在开始前刚好我有一些资料&#xff0c;是我根据网友给的问题精心整理了一份「嵌入式的资料从专业入门到高级教程」&#xff0c;点个关注在评论区回复“666”之后私信回复“666”&#xff0c;全部无偿共享给大家&#xff01;&#xff01;&#xff01; 在网络数据传输中&#xf…

基站光伏直流叠光能效管理方案

安科瑞 华楠 基站现状和趋势 5G基站是专门提供5G网络服务的公用移动通信基站。5G基站主要用于提供5G空口协议功能&#xff0c;支持与用户设备、核心网之间的通信。按照逻辑功能划分&#xff0c;5G基站可分为5G基带单元与5G射频单元&#xff0c;二者之间可通过CPRI或eCPRI接口…

Python3网络爬虫开发实战(3)网页数据的解析提取

文章目录 一、XPath1. 选取节点2. 查找某个特定的节点或者包含某个指定的值的节点3. XPath 运算符4. 节点轴5. 利用 lxml 使用 XPath 二、CSS三、Beautiful Soup1. 信息提取2. 嵌套选择3. 关联选择4. 方法选择器5. css 选择器 四、PyQuery1. 初始化2. css 选择器3. 信息提取4. …

【游戏制作】使用Python创建一个完整的2048游戏项目

目录 项目运行展示 项目概述 项目目标 项目结构 安装依赖 代码实现 1. 导入库 2. 创建 Game2048 类 3. 设置UI界面 4. 加载二维码图片 5. 创建菜单 6. 游戏逻辑和功能 7. 运行应用 总结 创建一个完整的2048游戏项目 项目运行展示 项目概述 在这个项目中&#xff…

TypeScript核心

常用操作方式 1、类型推断 ts会根据变量存放的初始值来进行变量类型限定。 如上&#xff1a;开始str是字符串&#xff0c;则此变量以后就只能存字符串值。 开发中的意义&#xff1a;变量分配字符串值&#xff0c;后期可能会书写一些字符串功能、方法等相关的操作&#xff0c;如…

在Linux中,部署及优化Tomcat

tomcat概述 自 2017 年 11月编程语言排行榜 Java 占比 13%,高居榜首&#xff0c;Tomcat 也一度成为 Java开发人员的首选。其开源、占用系统资源少、跨平台等特性深受广大程序员喜爱。本章主要学习如何部署 Tomcat 服务&#xff0c;根据生产环境实现多个虚拟主机的配置&#xf…

GPT-4引领:AI新浪潮的转折点

OneFlow编译 **翻译&#xff5c;贾川、杨婷、徐佳渝 编辑&#xff5c;王金许** 一朝成名天下知。ChatGPT/GPT-4相关的新闻接二连三刷屏朋友圈&#xff0c;如今&#xff0c;这些模型背后的公司OpenAI的知名度不亚于任何科技巨头。 不过&#xff0c;就在ChatGPT问世前&#x…

ISP 代理提供商:互联网安全的关键参与者

简介&#xff1a;互联网安全的演变态势 互联网改变了我们互动、工作和开展业务的方式&#xff0c;但也带来了与安全性和可访问性相关的重大挑战。在这个数字时代&#xff0c;互联网服务提供商 (ISP) 代理提供商在解决这些问题方面发挥着关键作用。他们提供的基本服务不仅可以增…

pytest使用

主要技术内容 1.pytest设计 接口测试 框架设想 common—公共的东西封装 1.request请求 2.Session 3.断言 4.Log 5.全局变量 6.shell命令 ❖ config---配置文件及读取 ❖ Log— ❖ payload—请求参数—*.yaml及读取 ❖ testcases—conftest.py; testcase1.py…….可…

Can we Deploy Web Application in Azure OpenAI of Production Level

题意&#xff1a;我们可以在Azure OpenAI中部署生产级别的Web应用程序吗 问题背景&#xff1a; I have created azure ai search service and used Text split skillset and made index. I also deployed a web Application but have a question that If I want to create to …

【React】JSX 实现列表渲染

文章目录 一、基础语法1. 使用 map() 方法2. key 属性的使用 二、常见错误和注意事项1. 忘记使用 key 属性2. key 属性的选择 三、列表渲染的高级用法1. 渲染嵌套列表2. 条件渲染列表项3. 动态生成组件 四、最佳实践 在 React 开发中&#xff0c;列表渲染是一个非常常见的需求。…

队列的实现

概念与结构 概念&#xff1a;只允许在⼀端进行插入数据操作&#xff0c;在另⼀端进行删除数据操作的特殊线性表&#xff0c;队列具有先进先出FIFO(First In First Out)。 入队列&#xff1a;进行插入操作的⼀端称为队尾。 出队列&#xff1a;进行删除操作的⼀端称为队头。 …

使用echo写入多行文字到文件时换行的处理

目标 想使用echo写入如下内容到文件program.c里 #include<stdio.h> int main(){printf("hello!\n"); } 需要处理 1、如何处理行换 2、代码中的换行如何处理 实际例子 创建文件夹 mkdir test cd test chmod 777 . 创建文件写入内容 查看 cat -n program.c…

基于PSO粒子群优化的GroupCNN分组卷积网络时间序列预测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 粒子群优化算法&#xff08;PSO&#xff09; 4.2 分组卷积神经网络&#xff08;GroupCNN&#xff09; 4.3 PSO优化GroupCNN 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行…

Mysql注意事项(一)

Mysql注意事项&#xff08;一&#xff09; 最近回顾了一下MySQL&#xff0c;发现了一些MySQL需要注意的事项&#xff0c;同时也作为学习笔记&#xff0c;记录下来。–2020年05月13日 1、通配符* 检索所有的列。 不建议使用 通常&#xff0c;除非你确定需要表中的每个列&am…

vue3前端开发-小兔鲜项目-form表单的统一校验

vue3前端开发-小兔鲜项目-form表单的统一校验&#xff01;实际上&#xff0c;为了安全起见&#xff0c;用户输入的表单信息&#xff0c;要满足我们的业务需求&#xff0c;参数类型等种种标准之后&#xff0c;才会允许用户向服务器发送登录请求。为此&#xff0c;有必要进行一次…