这段代码是一个基于 tkinter
的图形界面程序,用于实现一个照片压缩子系统。该程序提供了一个主页面和一个子系统页面,用户可以选择照片文件夹并对文件夹内的照片进行批量压缩。
以下是代码的主要部分:
MyApp
类:继承自tk.Tk
,用于创建应用程序的主窗口。主要创建了一个ttk.Notebook
,用于切换主页面和子系统页面。Page
类:用于创建页面的基类。每个页面都继承自这个类,包含一个框架,用于放置小部件。StartPage
类:继承自Page
类,用于创建主页面。在主页面上显示一个欢迎标签。Page2
类:继承自Page
类,用于创建子系统2页面。该页面包含了选择文件夹、压缩照片、重置等功能。利用PIL
库对图片进行压缩,并在文本框中显示操作信息。yasuo
方法:用于压缩照片,遍历文件夹中的图片文件,对图片进行压缩,并在进度条和文本框中显示操作信息。open_folder
方法:用于选择文件夹路径。set_entry
方法:用于清空文件夹路径和文本框内容。return_to_start
方法:用于返回主页面。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()
最新评论