使用 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 文件。

关键功能解析

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

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

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

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

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

结果如下

在这里插入图片描述

结论

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

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值