第一次用Python写东西,UI写的跟坨勾石一样。T-T
import os
import shutil
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox
from tkinter import ttk
from apscheduler.schedulers.background import BackgroundScheduler
from datetime import datetime, timedelta
from threading import Thread
class BackupTool:
def __init__(self, root):
self.root = root
self.root.title("备份工具")
self.source_folder = tk.StringVar()
self.dest_folder = tk.StringVar()
self.backup_list = []
self.replace_conflicts_var = tk.BooleanVar()
self.next_backup_time_var = tk.StringVar()
self.scheduler = BackgroundScheduler()
self.create_gui()
def create_gui(self):
tk.Label(self.root, text="源文件夹:").grid(row=0, column=0, padx=5, pady=5, sticky="e")
tk.Entry(self.root, textvariable=self.source_folder, state="readonly", width=40).grid(row=0, column=1, padx=5, pady=5)
tk.Button(self.root, text="浏览", command=self.browse_source_folder).grid(row=0, column=2, padx=5, pady=5)
tk.Label(self.root, text="目标文件夹:").grid(row=1, column=0, padx=5, pady=5, sticky="e")
tk.Entry(self.root, textvariable=self.dest_folder, state="readonly", width=40).grid(row=1, column=1, padx=5, pady=5)
tk.Button(self.root, text="浏览", command=self.browse_dest_folder).grid(row=1, column=2, padx=5, pady=5)
tk.Label(self.root, text="备份列表:").grid(row=2, column=0, padx=5, pady=5, sticky="e")
self.tree = ttk.Treeview(self.root, columns=("Folder",), show="headings", height=5)
self.tree.heading("Folder", text="文件夹")
self.tree.grid(row=3, column=0, columnspan=3, padx=5, pady=5)
tk.Button(self.root, text="添加备份任务", command=self.add_backup_task).grid(row=4, column=0, columnspan=3, padx=5, pady=5)
tk.Label(self.root, text="替换冲突:").grid(row=7, column=0, padx=5, pady=5, sticky="e")
tk.Checkbutton(self.root, variable=self.replace_conflicts_var).grid(row=7, column=1, padx=5, pady=5, sticky="w")
tk.Label(self.root, text="下次备份时间:").grid(row=6, column=0, padx=5, pady=5, sticky="e")
tk.Entry(self.root, textvariable=self.next_backup_time_var).grid(row=6, column=1, padx=5, pady=5)
tk.Button(self.root, text="立即备份", command=self.backup_now).grid(row=6, column=2, columnspan=1, padx=5, pady=5)
tk.Button(self.root, text="保存并开始任务", command=self.save_and_start_task).grid(row=8, column=1, padx=5, pady=5)
tk.Button(self.root, text="删除之前的配置", command=self.delete_previous_configurations).grid(row=8, column=0, padx=5, pady=5)
self.status_label = tk.Label(self.root, text="状态: 就绪", bd=1, relief="sunken", anchor="w")
self.status_label.grid(row=9, column=0, columnspan=3, sticky="we", padx=5, pady=5)
self.load_settings()
def browse_source_folder(self):
folder = filedialog.askdirectory()
if folder:
self.source_folder.set(folder)
def browse_dest_folder(self):
folder = filedialog.askdirectory()
if folder:
self.dest_folder.set(folder)
def add_backup_task(self):
folder = self.source_folder.get()
if folder and folder not in self.backup_list:
self.backup_list.append(folder)
self.tree.insert("", "end", values=(folder,))
self.start_backup_job()
def start_backup_job(self):
if not self.scheduler.running:
interval_minutes = 1 # 默认间隔为1分钟,根据需要更改
self.scheduler.add_job(self.backup_now, 'interval', minutes=interval_minutes)
self.scheduler.start()
def backup_now(self):
if self.backup_list:
dest_folder = self.dest_folder.get()
for folder in self.backup_list:
backup_folder = os.path.join(dest_folder, os.path.basename(folder))
try:
if os.path.exists(backup_folder):
if self.replace_conflicts_var.get():
shutil.rmtree(backup_folder)
else:
messagebox.showerror("错误", f"目标文件夹 '{backup_folder}' 已存在。")
self.stop_backup_job()
return
shutil.copytree(folder, backup_folder)
self.update_status(f"备份完成:{folder} 到 {backup_folder}")
except Exception as e:
messagebox.showerror("错误", f"备份时发生错误:{e}")
self.stop_backup_job()
return
self.update_status("备份完成。")
else:
messagebox.showinfo("信息", "没有添加备份任务。")
def stop_backup_job(self):
if self.scheduler.running:
self.scheduler.shutdown()
def load_settings(self):
try:
settings = {} # 从配置文件或其他持久化存储中加载设置
self.source_folder.set(settings.get("source_folder", ""))
self.dest_folder.set(settings.get("dest_folder", ""))
self.backup_list = settings.get("backup_list", "").split(",")
self.backup_list = [folder for folder in self.backup_list if folder]
for folder in self.backup_list:
self.tree.insert("", "end", values=(folder,))
self.replace_conflicts_var.set(settings.get("replace_conflicts", "False") == "True")
next_backup_time = settings.get("next_backup_time", "")
self.next_backup_time_var.set(next_backup_time)
if self.replace_conflicts_var.get():
self.update_status("替换冲突: 启用")
else:
self.update_status("替换冲突: 禁用")
self.update_status("设置已加载。")
except FileNotFoundError:
self.update_status("未找到先前的设置。")
def delete_previous_configurations(self):
self.source_folder.set("")
self.dest_folder.set("")
self.backup_list = []
self.tree.delete(*self.tree.get_children())
self.stop_backup_job()
self.next_backup_time_var.set("") # Clear next backup time
self.update_status("已删除先前的配置。")
def update_status(self, message):
self.status_label.config(text=f"状态: {message}")
def save_and_start_task(self):
self.save_settings()
self.start_backup_job()
def save_settings(self):
settings = {
"source_folder": self.source_folder.get(),
"dest_folder": self.dest_folder.get(),
"backup_list": ",".join(self.backup_list),
"replace_conflicts": str(self.replace_conflicts_var.get()),
"next_backup_time": self.next_backup_time_var.get(),
}
# 将设置保存到配置文件或其他持久化存储中
if __name__ == "__main__":
root = tk.Tk()
app = BackupTool(root)
root.mainloop()