使用 Python创建照片文件复制和压缩工具
在这篇博客中,我们将探索如何使用 wxPython 创建一个 GUI 工具,用于选择文件夹中的照片文件、显示预览、选择并复制文件到指定目录,以及将选中的照片压缩到一个 ZIP 文件中。这个工具不仅功能强大,而且提供了用户友好的界面。
C:\pythoncode\new\photofilecopyandzip.py
全部代码
import wx
import os
from datetime import datetime
import shutil
import zipfile
class 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_path
self.listView.SetItem(item_index, 2, dimensions)
self.listView.SetItem(item_index, 3, date)
self.image_paths[item_index] = img_path
def 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])) + now
zip_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 zipfile
class 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_path
def 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])) + now
zip_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 文件。
关键功能解析
-
打开文件夹:
使用wx.DirDialog
打开文件夹对话框,选择包含照片的文件夹。通过os.listdir
获取文件夹中的文件列表,并使用wx.Image
加载并显示图片。 -
显示图片预览:
当用户选择列表中的图片时,使用wx.StaticBitmap
显示图片的缩略图。 -
选择和取消选择:
提供全选和取消选择按钮,便于用户批量选择和取消选择照片文件。 -
复制照片:
通过shutil.copy
将选中的照片文件复制到指定目录。 -
压缩照片:
使用zipfile.ZipFile
创建 ZIP 文件,将选中的照片文件添加到 ZIP 文件中。
结果如下
结论
通过这篇博客,我们创建了一个功能全面的照片文件管理工具,能够帮助用户方便地选择、预览、复制和压缩照片文件。这个工具展示了 wxPython 在创建桌面应用程序时的强大功能和灵活性。希望你能从中学到有用的知识,并将其应用到你自己的项目中。
原文地址:https://blog.csdn.net/winniezhang/article/details/140722149
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!