欢迎光临UUpython
最大、最新、最全的Python代码收集站

[GUI]tkinter批量压缩图片

这段代码是一个基于 tkinter 的图形界面程序,用于实现一个照片压缩子系统。该程序提供了一个主页面和一个子系统页面,用户可以选择照片文件夹并对文件夹内的照片进行批量压缩。

以下是代码的主要部分:

  1. MyApp 类:继承自 tk.Tk,用于创建应用程序的主窗口。主要创建了一个 ttk.Notebook,用于切换主页面和子系统页面。
  2. Page 类:用于创建页面的基类。每个页面都继承自这个类,包含一个框架,用于放置小部件。
  3. StartPage 类:继承自 Page 类,用于创建主页面。在主页面上显示一个欢迎标签。
  4. Page2 类:继承自 Page 类,用于创建子系统2页面。该页面包含了选择文件夹、压缩照片、重置等功能。利用 PIL 库对图片进行压缩,并在文本框中显示操作信息。
  5. yasuo 方法:用于压缩照片,遍历文件夹中的图片文件,对图片进行压缩,并在进度条和文本框中显示操作信息。
  6. open_folder 方法:用于选择文件夹路径。
  7. set_entry 方法:用于清空文件夹路径和文本框内容。
  8. return_to_start 方法:用于返回主页面。
  9. if __name__ == "__main__":创建 MyApp 实例并运行主循环。

请注意,这是一个简化的示例代码,其中可能会缺少某些错误处理和细节。为了让程序更加健壮和完善,你可能需要添加一些错误处理、用户交互提示以及更详细的注释。

import tkinter as tk
from tkinter import ttk
from tkinter import filedialog
import tkinter.messagebox
from tkinter import scrolledtext#滚动文本框组件
from tkinter import Menu
from tkinter import ttk
import time
import re
import os
import os.path as osp
from PIL import Image#处理图片库
 
class MyApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("My App")
        self.geometry("1080x680+390+190")
        #self.resizable(0, 0)
        # 创建一个欢迎Label
        tk.Label(self, text='`欢迎进入百胜通信工程有限公司工作系统`', font=("楷体", 15)).pack(padx=20, pady=5)
        # 添加分隔线
        ttk.Separator(self, orient="horizontal").pack(fill="x")
        ttk.Separator(self, orient="horizontal").pack(fill="x")        
        # 创建Notebook小部件
        self.notebook = ttk.Notebook(self)
        self.notebook.pack(fill="both", expand=True)
                 
        # 创建页面列表,定义了一个名为pages的元组列表,其中每个元组包含页面的名称和实现页面的类
        pages = [
            ("主页面", StartPage),
            ("子系统2", Page2),
 
         
        ]
        # 使用循环创建页面
        for name, cls in pages:
            page = cls(self.notebook)
            self.notebook.add(page, text=name)
         
        # 修改选项卡文字字体
        style = ttk.Style()
        style.configure("TNotebook.Tab", font=("楷体", 10), foreground="red")
 
 
# 创建了一个名为Page的基类
class Page(ttk.Frame):
    def __init__(self, parent, name):
        super().__init__(parent)
        self.name = name
        # 添加分隔线
        ttk.Separator(self, orient="horizontal").pack(fill='x')
        ttk.Separator(self, orient="horizontal").pack(fill='x')
        # 创建一个Frame框架
        self.frame = tk.Frame(self, width=800, height=850, highlightbackground="black", highlightthickness=1, bd=3)
        self.frame.pack(side='left', fill='y', padx=135, pady=10)  # side设置left从左至右排列,fill设置y垂直方向填充空白方式
        #添加到父容器中
        self.pack(fill=tk.BOTH, expand=True)  # self.master.pack()就会卡死
# 创建从Page基类派生出每个页面的子类。每个子类都包含该页面的所有小部件和方法
class StartPage(Page):
    def __init__(self, parent):
        super().__init__(parent, "Start_Page")
        tk.Label(self.frame, text="这是主页面").place(relx=0.5, rely=0.0, anchor='n')
 
class Page2(Page):
    def __init__(self, parent):
        super().__init__(parent, "子系统2")
        self.pic=[]#照片文件夹列表
        self.dic={}#存放文件夹名和文件夹内文件名的键值对
        self.createWidget()
    def createWidget(self):
        tk.Label(self.frame, text="**********照片压缩子系统**********", width=40, height=2, font=("黑体", 15)).place(relx=0.5, rely=0.0, anchor='n')
        tk.Label(self.frame, text="目录路径:", bd=5, width=10, height=2, font=("楷体", 15)).place(x=142, y=100)
        self.lujing = tk.Entry(self.frame, width=25)
        self.lujing.place(x=238, y=116)
        # bind()方法将open_folder()函数与“<Return>”键绑定,以便在用户按下“Enter”键时自动打开所选的文件夹
        #self.lujing.bind("<Return>", self.open_folder)
        tk.Button(self.frame, text="选择", font=("楷体", 11), width=3, height=1,bg='#BFEFFA',
                   command=self.open_folder).place(x=420, y=113)
        tk.Button(self.frame, text="压缩", font=("楷体", 11), width=3, height=1,bg='#BFEFFA',
                   command=self.yasuo).place(x=465, y=113)
        tk.Button(self.frame, text="重置", font=("楷体", 11), width=3, height=1,bg='#BFEFFA',
                   command=self.set_entry).place(x=300, y=480)        
        tk.Button(self.frame, text="返回主页面", font=("楷体", 11), width=10, height=1, command=self.return_to_start)\
        .place(x=350, y=480)#返回主页面
              
        self.texts = tk.Text(self.frame, font=('FangSong', 12), width=63, height=20)
        self.texts.place(x=150, y=142)  # 如果这行代码不单独写,下面代码就会报错'NoneType' object has no attribute 'insert'
        #添加垂直滚动条
        scrollbar = ttk.Scrollbar(self.frame,command=self.texts.yview)
        scrollbar.place(x=639, y=145, height=318)
        self.texts.config(yscrollcommand=scrollbar.set)
        self.texts.insert(tk.END, '已压缩的照片:\n')
         
    def yasuo(self):
        reg1=re.compile(r'\.(jpg|png)$')
        reg2=re.compile(r'(?<=IMG_)\d+_\d+(?=.jpg)')#匹配\d+_\d+
        folder_path = self.lujing.get()  # 获取已经选择的文件夹路径
        pics = os.listdir(folder_path)
        # 添加路径
        prefix = folder_path
        self.pic = [os.path.join(prefix,str(x)) for x in pics]
        if not all([folder_path]):
            tkinter.messagebox.showerror("无法压缩!", "请填写文件夹路径")
           #获取图片的文件名,并拼接完整路径            `
            self.pic.extend(list_j)
 
        for i in range(len(self.pic)):
            name,exc=osp.split(self.pic[i])#osp.splitext()返回一个文件路径,和文件后缀组成的元组,所以name是一个文件路径。而os.path.split():返回一个路径的目录名和文件名(带后缀)
            nam=osp.basename(name)
            self.dic[nam]=[osp.join(name,exc) for exc in os.listdir(name) if osp.isfile(osp.join(name,exc))
                                                                   if reg1.findall(exc)]#字典的键是唯一的,dic[nam]所以会自动去重
        #print(self.dic)
        #可以利用字典构造DataFrane                                                           
        #df=pd.DataFrame.from_dict(data=dic,orient="columns")
        #进度条
        progress = ttk.Progressbar(self.frame,orient="horizontal",length=155, mode="determinate")
        progress.place(x=500, y=113)
        progress["maximum"] = len(self.pic)#进度条最大值
        progress["value"] = 0#进度条当前值 
        for key,item in self.dic.items():
            #print(f"开始压缩:{key}文件夹内的照片..")
            self.texts.insert(tk.END,f"{key}文件夹内的照片..\n")            
            for file in item:
                im = Image.open(file)#打开里面的jpg文件
                (x,y) = im.size #读取图片尺寸(像素)
                x_s = 2000 #定义缩小后的标准宽度 
                y_s = int(y * x_s / x) #基于标准宽度计算缩小后的高度
                out = im.resize((x_s,y_s),Image.Resampling.LANCZOS) #改变尺寸,保持图片高品质
                out.save(file)#原路径保存
                progress.step(1)
                progress.update()  # 手动更新进度条,没有此代码进度条不显示  
                na,ex=osp.split(file)
                #print(f'{ex}-压缩完成') 
                self.texts.insert(tk.END,f'{ex}-压缩完成\n')
            #print()
            self.texts.insert(tk.END, "\n")#空行
        self.texts.insert(tk.END, f"本次系统共压缩了{len(self.dic)}个照片文件夹"+f'共{len(self.pic)}张照片\n')    
        progress.destroy()#销毁进度条
        tkinter.messagebox.showinfo("压缩完成", f"本次系统共压缩了{len(self.dic)}个照片文件夹"+f',共{len(self.pic)}张照片\n')
 
 
    def return_to_start(self):#返回主页面函数
        self.master.master.notebook.select(0)
    def open_folder(self, event=None):
        folder_path = self.lujing.get()  # 取文本框的值,获取目前Entry的字符串内容
        self.folder_path = folder_path
        self.folder_dialog = filedialog.askdirectory(initialdir=folder_path, title='选择')  # 对话框
        # self.lujing.delete(0, tk.END)  # 清空Entry控件中的内容
        self.lujing.insert(0, self.folder_dialog)  # 将选择的文件夹路径更新到Entry控件中
    def set_entry(self):
        self.lujing.delete(0, tk.END)
        self.texts.delete('1.0', tk.END)  # 清空Text文本框内容
        self.pic=[]#清空照片文件夹列表
        self.dic={}#清空存放文件夹名和文件夹内文件名的键值对字典
 
 
         
 
if __name__ == "__main__":
    app = MyApp()
    app.mainloop()
赞(0) 打赏
未经允许不得转载:UUpython » [GUI]tkinter批量压缩图片
分享到: 更多 (0)

评论 抢沙发

评论前必须登录!