""" 作者:太一 微信:taiyi1224 邮箱:shuobo1224@qq.com """ import tkinter as tk from tkinter import ttk, messagebox, filedialog from tkinter import TclError import math from template_presets import TemplatePresetManager class TemplateDialog(tk.Toplevel): """模板选择对话框""" def __init__(self, parent, current_template): super().__init__(parent) self.title("模板设置") self.parent = parent self.current_template = current_template self.result = None # 初始化预设管理器 self.preset_manager = TemplatePresetManager() # 确保对话框模态 self.transient(parent) self.grab_set() # 设置布局 frame = ttk.Frame(self, padding=10) frame.pack(fill=tk.BOTH, expand=True) # 预设管理 preset_frame = ttk.LabelFrame(frame, text="模板预设", padding=5) preset_frame.grid(row=0, column=0, columnspan=3, sticky=tk.EW, pady=(0, 10)) ttk.Label(preset_frame, text="选择预设:").grid(row=0, column=0, sticky=tk.W) self.preset_var = tk.StringVar() # 默认空字符串,不选中任何预设 self.preset_combo = ttk.Combobox(preset_frame, textvariable=self.preset_var, width=30) self.preset_combo.grid(row=0, column=1, padx=5) self.update_preset_list() ttk.Button(preset_frame, text="加载", command=self.load_selected_preset).grid(row=0, column=2, padx=5) ttk.Button(preset_frame, text="保存当前为预设", command=self.save_current_as_preset).grid(row=0, column=3, padx=5) ttk.Button(preset_frame, text="删除选中预设", command=self.delete_selected_preset).grid(row=0, column=4, padx=5) # 比例选择 ttk.Label(frame, text="选择比例:").grid(row=1, column=0, sticky=tk.W, pady=5) self.ratio_var = tk.StringVar(value=f"{current_template.ratio[0]}:{current_template.ratio[1]}") ratio_frame = ttk.Frame(frame) ratio_frame.grid(row=1, column=1, sticky=tk.W, pady=5) ratios = ["16:9", "3:4", "9:16", "4:3", "自定义"] for i, ratio in enumerate(ratios): ttk.Radiobutton( ratio_frame, text=ratio, variable=self.ratio_var, value=ratio, command=self.on_ratio_change ).grid(row=0, column=i, padx=5) # 自定义尺寸(默认隐藏) self.custom_frame = ttk.Frame(frame) ttk.Label(self.custom_frame, text="宽度:").grid(row=0, column=0, sticky=tk.W) self.width_var = tk.IntVar(value=current_template.width_px) width_entry = ttk.Entry(self.custom_frame, textvariable=self.width_var, width=8) width_entry.grid(row=0, column=1, padx=5) width_entry.bind("", self.on_custom_size_change) ttk.Label(self.custom_frame, text="高度:").grid(row=0, column=2, sticky=tk.W, padx=5) self.height_var = tk.IntVar(value=current_template.height_px) height_entry = ttk.Entry(self.custom_frame, textvariable=self.height_var, width=8) height_entry.grid(row=0, column=3, padx=5) height_entry.bind("", self.on_custom_size_change) # 背景设置 ttk.Label(frame, text="背景颜色:").grid(row=3, column=0, sticky=tk.W, pady=5) self.bg_color_var = tk.StringVar(value=current_template.bg_color) ttk.Entry(frame, textvariable=self.bg_color_var, width=10).grid(row=3, column=1, sticky=tk.W, pady=5) ttk.Label(frame, text="背景图:").grid(row=4, column=0, sticky=tk.W, pady=5) self.bg_image_var = tk.StringVar(value="无" if current_template.bg_image is None else "已设置") ttk.Label(frame, textvariable=self.bg_image_var).grid(row=4, column=1, sticky=tk.W, pady=5) btn_frame = ttk.Frame(frame) ttk.Button(btn_frame, text="选择背景图", command=self.choose_bg_image).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="清除背景图", command=self.clear_bg_image).pack(side=tk.LEFT, padx=5) btn_frame.grid(row=4, column=2, sticky=tk.W, pady=5) # 确认和取消按钮 btn_frame = ttk.Frame(frame) ttk.Button(btn_frame, text="确定", command=self.on_ok).pack(side=tk.LEFT, padx=5) ttk.Button(btn_frame, text="取消", command=self.on_cancel).pack(side=tk.LEFT, padx=5) btn_frame.grid(row=5, column=0, columnspan=3, pady=10) # 检查当前是否为自定义比例 if f"{current_template.ratio[0]}:{current_template.ratio[1]}" not in ratios: self.ratio_var.set("自定义") self.show_custom_frame() else: self.hide_custom_frame() # 调整大小 self.geometry("700x300") self.wait_window(self) def update_preset_list(self): """更新预设列表""" presets = self.preset_manager.get_presets() preset_names = [preset["name"] for preset in presets["presets"]] self.preset_combo['values'] = preset_names # 不自动选中任何预设,让用户手动选择 def load_selected_preset(self): """加载选中的预设""" selected_preset = self.preset_var.get() if not selected_preset: messagebox.showwarning("警告", "请先选择一个预设") return # 设置标志以避免在刷新界面时更改尺寸 self._loading_preset = True if self.preset_manager.load_preset_to_template(selected_preset, self.current_template): # 更新界面显示 self.refresh_from_template() # 刷新主窗口画布 self.parent.get_canvas().draw_preview() messagebox.showinfo("成功", f"已加载预设: {selected_preset}") else: messagebox.showerror("错误", "加载预设失败") # 清除标志 self._loading_preset = False def save_current_as_preset(self): """将当前设置保存为预设""" # 弹出输入框获取预设名称 preset_name = tk.simpledialog.askstring("保存预设", "请输入预设名称:") if not preset_name: return # 保存当前模板为预设 if self.preset_manager.save_current_template_as_preset(self.current_template, preset_name): # 更新预设列表 self.update_preset_list() messagebox.showinfo("成功", f"预设已保存: {preset_name}") else: messagebox.showerror("错误", "保存预设失败") def delete_selected_preset(self): """删除选中的预设""" selected_preset = self.preset_var.get() if not selected_preset: messagebox.showwarning("警告", "请先选择一个预设") return if messagebox.askyesno("确认", f"确定要删除预设 '{selected_preset}' 吗?"): if self.preset_manager.remove_preset(selected_preset): self.update_preset_list() messagebox.showinfo("成功", f"预设已删除: {selected_preset}") else: messagebox.showerror("错误", "删除预设失败") def refresh_from_template(self): """根据当前模板刷新界面""" # 更新比例选择 ratio_str = f"{self.current_template.ratio[0]}:{self.current_template.ratio[1]}" self.ratio_var.set(ratio_str) # 更新尺寸 self.width_var.set(self.current_template.width_px) self.height_var.set(self.current_template.height_px) # 更新背景颜色 self.bg_color_var.set(self.current_template.bg_color) # 更新背景图状态 self.bg_image_var.set("无" if self.current_template.bg_image is None else "已设置") # 处理自定义比例显示 ratios = ["16:9", "3:4", "9:16", "4:3"] if ratio_str in ratios: self.hide_custom_frame() else: self.show_custom_frame() def on_ratio_change(self): if self.ratio_var.get() == "自定义": self.show_custom_frame() # 更新比例显示为当前模板的比例 ratio_str = f"{self.current_template.ratio[0]}:{self.current_template.ratio[1]}" self.ratio_var.set(ratio_str) else: self.hide_custom_frame() if not (hasattr(self, '_loading_preset') and self._loading_preset): try: w, h = map(int, self.ratio_var.get().split(":")) current_width = self.width_var.get() if current_width <= 0: current_width = 100 # 避免宽度为0 new_height = int(current_width * h / w) new_height = max(10, new_height) # 确保最小高度 self.height_var.set(new_height) # 同步更新当前模板的尺寸 self.current_template.width_px = current_width self.current_template.height_px = new_height self.current_template.ratio = (w, h) except (ValueError, ZeroDivisionError): messagebox.showerror("错误", "无效的比例格式") def show_custom_frame(self): """显示自定义尺寸框""" self.custom_frame.grid(row=2, column=0, columnspan=3, sticky=tk.W, pady=5) def hide_custom_frame(self): """隐藏自定义尺寸框""" self.custom_frame.grid_forget() def on_custom_size_change(self, event=None): """自定义尺寸变化时的处理""" if self.ratio_var.get() == "自定义": try: width = self.width_var.get() height = self.height_var.get() if width <= 0 or height <= 0: return # 更新当前模板的尺寸 self.current_template.set_custom_size(width, height) # 更新比例显示 ratio_str = f"{self.current_template.ratio[0]}:{self.current_template.ratio[1]}" self.ratio_var.set(ratio_str) # 刷新主窗口画布 self.parent.get_canvas().draw_preview() except (ValueError, TclError): # 忽略无效输入 pass def choose_bg_image(self): """选择背景图""" file_path = filedialog.askopenfilename( title="选择背景图", filetypes=[("图片文件", "*.png *.jpg *.jpeg *.gif *.bmp")] ) if file_path: if self.current_template.load_background(file_path): self.bg_image_var.set("已设置") # 刷新主窗口画布 self.parent.get_canvas().draw_preview() else: messagebox.showerror("错误", "加载背景图失败") def clear_bg_image(self): """清除背景图""" self.current_template.clear_background() self.bg_image_var.set("无") # 刷新主窗口画布 self.parent.get_canvas().draw_preview() def on_ok(self): """确认按钮""" # 只有在用户主动点击"加载"按钮加载预设时才应用预设 # 不再自动应用选中的预设 try: if self.ratio_var.get() == "自定义": try: width = self.width_var.get() height = self.height_var.get() except tk.TclError: messagebox.showerror("错误", "请输入有效的整数") return if width <= 0 or height <= 0: messagebox.showerror("错误", "宽度和高度必须为正数") return # 更新当前模板 self.current_template.set_custom_size(width, height) # 显式设置ratio属性为自定义比例 gcd = math.gcd(width, height) ratio_w = width // gcd ratio_h = height // gcd self.current_template.ratio = (ratio_w, ratio_h) self.current_template.bg_color = self.bg_color_var.get() self.result = { "type": "custom", "width": width, "height": height, "ratio": (ratio_w, ratio_h), "bg_color": self.bg_color_var.get(), "bg_image": self.current_template.bg_image, "bg_image_path": self.current_template.bg_image_path } else: w, h = map(int, self.ratio_var.get().split(":")) # 更新当前模板 self.current_template.ratio = (w, h) self.current_template.width_px = self.width_var.get() self.current_template.height_px = self.height_var.get() self.current_template.bg_color = self.bg_color_var.get() self.result = { "type": "preset", "ratio": tuple([w, h]), "width": self.width_var.get(), "height": self.height_var.get(), "bg_color": self.bg_color_var.get(), "bg_image": self.current_template.bg_image, "bg_image_path": self.current_template.bg_image_path } self.destroy() except Exception as e: messagebox.showerror("错误", f"设置模板失败: {str(e)}") def on_cancel(self): """取消按钮""" self.result = None self.destroy()