成品内容
This commit is contained in:
parent
fc83bb0bfc
commit
91a353b0f9
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
from PIL import Image, ImageTk
|
from PIL import Image, ImageTk
|
||||||
@ -36,6 +42,9 @@ class CanvasWidget(tk.Canvas):
|
|||||||
# 初始绘制
|
# 初始绘制
|
||||||
self.draw_preview()
|
self.draw_preview()
|
||||||
|
|
||||||
|
def on_template_changed(self):
|
||||||
|
"""当模板变化时重绘画布"""
|
||||||
|
self.draw_preview()
|
||||||
def canvas_to_template(self, x, y):
|
def canvas_to_template(self, x, y):
|
||||||
"""将画布坐标转换为模板坐标"""
|
"""将画布坐标转换为模板坐标"""
|
||||||
scale = self.zoom
|
scale = self.zoom
|
||||||
@ -204,16 +213,16 @@ class CanvasWidget(tk.Canvas):
|
|||||||
if img:
|
if img:
|
||||||
# 应用遮罩
|
# 应用遮罩
|
||||||
masked_img = ImageManager.apply_mask(img, fg.mask_shape)
|
masked_img = ImageManager.apply_mask(img, fg.mask_shape)
|
||||||
|
|
||||||
# 使用基于顶点的图像变形方法
|
# 使用基于顶点的图像变形方法
|
||||||
transformed_img, (x, y) = ImageManager.transform_with_vertices(
|
transformed_img, (x, y) = ImageManager.transform_with_vertices(
|
||||||
masked_img, fg.vertices
|
masked_img, fg.vertices
|
||||||
)
|
)
|
||||||
|
|
||||||
# 确保图像具有透明度
|
# 确保图像具有透明度
|
||||||
if transformed_img.mode != 'RGBA':
|
if transformed_img.mode != 'RGBA':
|
||||||
transformed_img = transformed_img.convert('RGBA')
|
transformed_img = transformed_img.convert('RGBA')
|
||||||
|
|
||||||
# 缩放到预览尺寸
|
# 缩放到预览尺寸
|
||||||
scaled_img = transformed_img.resize(
|
scaled_img = transformed_img.resize(
|
||||||
(max(1, int(transformed_img.width * self.zoom)),
|
(max(1, int(transformed_img.width * self.zoom)),
|
||||||
|
|||||||
@ -1,6 +1,19 @@
|
|||||||
"""导出设置对话框"""
|
"""导出设置对话框"""
|
||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk, filedialog, messagebox
|
from tkinter import ttk, filedialog, messagebox
|
||||||
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from exporter import Exporter
|
from exporter import Exporter
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from concurrent.futures import ThreadPoolExecutor, as_completed
|
from concurrent.futures import ThreadPoolExecutor, as_completed
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from PIL import Image, ImageDraw, ImageOps
|
from PIL import Image, ImageDraw, ImageOps
|
||||||
|
|||||||
11
main.py
11
main.py
@ -1,3 +1,14 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from main_window import MainWindow
|
from main_window import MainWindow
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk, messagebox, filedialog, simpledialog
|
from tkinter import ttk, messagebox, filedialog, simpledialog
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@ -173,7 +179,7 @@ class MainWindow(tk.Tk):
|
|||||||
if file_paths:
|
if file_paths:
|
||||||
# 检查是否是第一次添加图片
|
# 检查是否是第一次添加图片
|
||||||
is_first_batch = len(self.project.foregrounds) == 0
|
is_first_batch = len(self.project.foregrounds) == 0
|
||||||
|
|
||||||
# 添加所有选择的图片
|
# 添加所有选择的图片
|
||||||
added_foregrounds = []
|
added_foregrounds = []
|
||||||
for file_path in file_paths:
|
for file_path in file_paths:
|
||||||
@ -181,19 +187,19 @@ class MainWindow(tk.Tk):
|
|||||||
if not any(fg.file_path == file_path for fg in self.project.foregrounds):
|
if not any(fg.file_path == file_path for fg in self.project.foregrounds):
|
||||||
fg = self.project.add_foreground(file_path)
|
fg = self.project.add_foreground(file_path)
|
||||||
added_foregrounds.append(fg)
|
added_foregrounds.append(fg)
|
||||||
|
|
||||||
# 如果是第一次批量添加,则设置批量处理模式
|
# 如果是第一次批量添加,则设置批量处理模式
|
||||||
if is_first_batch and len(added_foregrounds) > 1:
|
if is_first_batch and len(added_foregrounds) > 1:
|
||||||
# 第一张图片保持可见和可编辑
|
# 第一张图片保持可见和可编辑
|
||||||
first_fg = added_foregrounds[0]
|
first_fg = added_foregrounds[0]
|
||||||
first_fg.hidden = False
|
first_fg.hidden = False
|
||||||
first_fg.visible = True
|
first_fg.visible = True
|
||||||
|
|
||||||
# 其他图片设置为隐藏
|
# 其他图片设置为隐藏
|
||||||
for fg in added_foregrounds[1:]:
|
for fg in added_foregrounds[1:]:
|
||||||
fg.hidden = True
|
fg.hidden = True
|
||||||
fg.visible = False
|
fg.visible = False
|
||||||
|
|
||||||
# 选中第一张图片
|
# 选中第一张图片
|
||||||
self.canvas.selected_item = first_fg
|
self.canvas.selected_item = first_fg
|
||||||
self.update_property_panel(first_fg)
|
self.update_property_panel(first_fg)
|
||||||
@ -264,19 +270,43 @@ class MainWindow(tk.Tk):
|
|||||||
"""设置模板"""
|
"""设置模板"""
|
||||||
dialog = TemplateDialog(self, self.project.template)
|
dialog = TemplateDialog(self, self.project.template)
|
||||||
if dialog.result:
|
if dialog.result:
|
||||||
if dialog.result["type"] == "preset":
|
# 处理所有类型的模板设置结果
|
||||||
self.project.template = Template(
|
if dialog.result["type"] == "preset_loaded":
|
||||||
dialog.result["ratio"],
|
# 直接更新现有模板的属性
|
||||||
dialog.result["width"]
|
self.project.template.ratio = dialog.result["ratio"]
|
||||||
)
|
self.project.template.width_px = dialog.result["width"]
|
||||||
else:
|
self.project.template.height_px = dialog.result["height"]
|
||||||
self.project.template = Template()
|
self.project.template.bg_color = dialog.result["bg_color"]
|
||||||
|
if "bg_image_path" in dialog.result and dialog.result["bg_image_path"]:
|
||||||
|
self.project.template.load_background(dialog.result["bg_image_path"])
|
||||||
|
elif dialog.result["type"] == "preset":
|
||||||
|
# 更新现有模板的属性
|
||||||
|
self.project.template.ratio = tuple(dialog.result["ratio"])
|
||||||
|
self.project.template.width_px = dialog.result["width"]
|
||||||
|
self.project.template.height_px = dialog.result["height"]
|
||||||
|
self.project.template.bg_color = dialog.result["bg_color"]
|
||||||
|
# 设置背景图
|
||||||
|
if "bg_image_path" in dialog.result and dialog.result["bg_image_path"]:
|
||||||
|
self.project.template.load_background(dialog.result["bg_image_path"])
|
||||||
|
elif "bg_image" in dialog.result:
|
||||||
|
self.project.template.bg_image = dialog.result["bg_image"]
|
||||||
|
elif dialog.result["type"] == "custom":
|
||||||
|
# 更新现有模板的属性
|
||||||
self.project.template.set_custom_size(
|
self.project.template.set_custom_size(
|
||||||
dialog.result["width"],
|
dialog.result["width"],
|
||||||
dialog.result["height"]
|
dialog.result["height"]
|
||||||
)
|
)
|
||||||
|
# 设置ratio属性
|
||||||
|
if "ratio" in dialog.result:
|
||||||
|
self.project.template.ratio = dialog.result["ratio"]
|
||||||
|
self.project.template.bg_color = dialog.result["bg_color"]
|
||||||
|
# 设置背景图
|
||||||
|
if "bg_image_path" in dialog.result and dialog.result["bg_image_path"]:
|
||||||
|
self.project.template.load_background(dialog.result["bg_image_path"])
|
||||||
|
elif "bg_image" in dialog.result:
|
||||||
|
self.project.template.bg_image = dialog.result["bg_image"]
|
||||||
|
|
||||||
self.project.template.bg_color = dialog.result["bg_color"]
|
# 确保更新画布显示
|
||||||
self.canvas.draw_preview()
|
self.canvas.draw_preview()
|
||||||
|
|
||||||
def batch_export(self):
|
def batch_export(self):
|
||||||
@ -300,7 +330,7 @@ class MainWindow(tk.Tk):
|
|||||||
if self.project.foregrounds:
|
if self.project.foregrounds:
|
||||||
first_image_dir = Path(self.project.foregrounds[0].file_path).parent
|
first_image_dir = Path(self.project.foregrounds[0].file_path).parent
|
||||||
default_output_dir = first_image_dir / "output"
|
default_output_dir = first_image_dir / "output"
|
||||||
|
|
||||||
dialog = ExportDialog(self, len(self.project.foregrounds))
|
dialog = ExportDialog(self, len(self.project.foregrounds))
|
||||||
if dialog.result:
|
if dialog.result:
|
||||||
# 禁用主窗口防止重复操作
|
# 禁用主窗口防止重复操作
|
||||||
|
|||||||
21
models.py
21
models.py
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import json
|
import json
|
||||||
@ -124,13 +130,13 @@ class Template:
|
|||||||
self.width_px = width_px
|
self.width_px = width_px
|
||||||
self.height_px = int(width_px * ratio[1] / ratio[0])
|
self.height_px = int(width_px * ratio[1] / ratio[0])
|
||||||
self.bg_image = None
|
self.bg_image = None
|
||||||
|
self.bg_image_path = None # 背景图片路径
|
||||||
self.bg_color = "#FFFFFF" # 默认白色背景
|
self.bg_color = "#FFFFFF" # 默认白色背景
|
||||||
|
|
||||||
|
# models.py 中 set_custom_size 方法添加通知机制
|
||||||
def set_custom_size(self, width, height):
|
def set_custom_size(self, width, height):
|
||||||
"""设置自定义尺寸"""
|
|
||||||
self.width_px = width
|
self.width_px = width
|
||||||
self.height_px = height
|
self.height_px = height
|
||||||
# 根据实际尺寸设置比例
|
|
||||||
gcd = math.gcd(width, height)
|
gcd = math.gcd(width, height)
|
||||||
self.ratio = (width // gcd, height // gcd)
|
self.ratio = (width // gcd, height // gcd)
|
||||||
|
|
||||||
@ -138,6 +144,7 @@ class Template:
|
|||||||
"""加载背景图"""
|
"""加载背景图"""
|
||||||
try:
|
try:
|
||||||
self.bg_image = Image.open(file_path).convert("RGBA")
|
self.bg_image = Image.open(file_path).convert("RGBA")
|
||||||
|
self.bg_image_path = file_path # 保存背景图片路径
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"加载背景图失败: {e}")
|
print(f"加载背景图失败: {e}")
|
||||||
@ -146,6 +153,7 @@ class Template:
|
|||||||
def clear_background(self):
|
def clear_background(self):
|
||||||
"""清除背景图"""
|
"""清除背景图"""
|
||||||
self.bg_image = None
|
self.bg_image = None
|
||||||
|
self.bg_image_path = None
|
||||||
|
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
"""转换为字典,用于序列化"""
|
"""转换为字典,用于序列化"""
|
||||||
@ -153,7 +161,8 @@ class Template:
|
|||||||
"ratio": self.ratio,
|
"ratio": self.ratio,
|
||||||
"width_px": self.width_px,
|
"width_px": self.width_px,
|
||||||
"height_px": self.height_px,
|
"height_px": self.height_px,
|
||||||
"bg_color": self.bg_color
|
"bg_color": self.bg_color,
|
||||||
|
"bg_image_path": self.bg_image_path
|
||||||
}
|
}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ -162,6 +171,12 @@ class Template:
|
|||||||
template = cls(data["ratio"], data["width_px"])
|
template = cls(data["ratio"], data["width_px"])
|
||||||
template.height_px = data["height_px"]
|
template.height_px = data["height_px"]
|
||||||
template.bg_color = data.get("bg_color", "#FFFFFF")
|
template.bg_color = data.get("bg_color", "#FFFFFF")
|
||||||
|
template.bg_image_path = data.get("bg_image_path")
|
||||||
|
|
||||||
|
# 如果存在背景图片路径,加载背景图片
|
||||||
|
if template.bg_image_path:
|
||||||
|
template.load_background(template.bg_image_path)
|
||||||
|
|
||||||
return template
|
return template
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,13 @@
|
|||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import ttk, messagebox, filedialog
|
from tkinter import ttk, messagebox, filedialog
|
||||||
|
from tkinter import TclError
|
||||||
|
import math
|
||||||
from template_presets import TemplatePresetManager
|
from template_presets import TemplatePresetManager
|
||||||
|
|
||||||
|
|
||||||
@ -29,7 +37,7 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
preset_frame.grid(row=0, column=0, columnspan=3, sticky=tk.EW, pady=(0, 10))
|
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)
|
ttk.Label(preset_frame, text="选择预设:").grid(row=0, column=0, sticky=tk.W)
|
||||||
self.preset_var = tk.StringVar()
|
self.preset_var = tk.StringVar() # 默认空字符串,不选中任何预设
|
||||||
self.preset_combo = ttk.Combobox(preset_frame, textvariable=self.preset_var, width=30)
|
self.preset_combo = ttk.Combobox(preset_frame, textvariable=self.preset_var, width=30)
|
||||||
self.preset_combo.grid(row=0, column=1, padx=5)
|
self.preset_combo.grid(row=0, column=1, padx=5)
|
||||||
self.update_preset_list()
|
self.update_preset_list()
|
||||||
@ -58,11 +66,15 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
self.custom_frame = ttk.Frame(frame)
|
self.custom_frame = ttk.Frame(frame)
|
||||||
ttk.Label(self.custom_frame, text="宽度:").grid(row=0, column=0, sticky=tk.W)
|
ttk.Label(self.custom_frame, text="宽度:").grid(row=0, column=0, sticky=tk.W)
|
||||||
self.width_var = tk.IntVar(value=current_template.width_px)
|
self.width_var = tk.IntVar(value=current_template.width_px)
|
||||||
ttk.Entry(self.custom_frame, textvariable=self.width_var, width=8).grid(row=0, column=1, padx=5)
|
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("<FocusOut>", self.on_custom_size_change)
|
||||||
|
|
||||||
ttk.Label(self.custom_frame, text="高度:").grid(row=0, column=2, sticky=tk.W, padx=5)
|
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)
|
self.height_var = tk.IntVar(value=current_template.height_px)
|
||||||
ttk.Entry(self.custom_frame, textvariable=self.height_var, width=8).grid(row=0, column=3, padx=5)
|
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("<FocusOut>", self.on_custom_size_change)
|
||||||
|
|
||||||
# 背景设置
|
# 背景设置
|
||||||
ttk.Label(frame, text="背景颜色:").grid(row=3, column=0, sticky=tk.W, pady=5)
|
ttk.Label(frame, text="背景颜色:").grid(row=3, column=0, sticky=tk.W, pady=5)
|
||||||
@ -100,8 +112,7 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
presets = self.preset_manager.get_presets()
|
presets = self.preset_manager.get_presets()
|
||||||
preset_names = [preset["name"] for preset in presets["presets"]]
|
preset_names = [preset["name"] for preset in presets["presets"]]
|
||||||
self.preset_combo['values'] = preset_names
|
self.preset_combo['values'] = preset_names
|
||||||
if preset_names:
|
# 不自动选中任何预设,让用户手动选择
|
||||||
self.preset_combo.current(0)
|
|
||||||
|
|
||||||
def load_selected_preset(self):
|
def load_selected_preset(self):
|
||||||
"""加载选中的预设"""
|
"""加载选中的预设"""
|
||||||
@ -110,6 +121,8 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
messagebox.showwarning("警告", "请先选择一个预设")
|
messagebox.showwarning("警告", "请先选择一个预设")
|
||||||
return
|
return
|
||||||
|
|
||||||
|
# 设置标志以避免在刷新界面时更改尺寸
|
||||||
|
self._loading_preset = True
|
||||||
if self.preset_manager.load_preset_to_template(selected_preset, self.current_template):
|
if self.preset_manager.load_preset_to_template(selected_preset, self.current_template):
|
||||||
# 更新界面显示
|
# 更新界面显示
|
||||||
self.refresh_from_template()
|
self.refresh_from_template()
|
||||||
@ -118,6 +131,8 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
messagebox.showinfo("成功", f"已加载预设: {selected_preset}")
|
messagebox.showinfo("成功", f"已加载预设: {selected_preset}")
|
||||||
else:
|
else:
|
||||||
messagebox.showerror("错误", "加载预设失败")
|
messagebox.showerror("错误", "加载预设失败")
|
||||||
|
# 清除标志
|
||||||
|
self._loading_preset = False
|
||||||
|
|
||||||
def save_current_as_preset(self):
|
def save_current_as_preset(self):
|
||||||
"""将当前设置保存为预设"""
|
"""将当前设置保存为预设"""
|
||||||
@ -172,15 +187,28 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
self.show_custom_frame()
|
self.show_custom_frame()
|
||||||
|
|
||||||
def on_ratio_change(self):
|
def on_ratio_change(self):
|
||||||
"""处理比例变化"""
|
|
||||||
if self.ratio_var.get() == "自定义":
|
if self.ratio_var.get() == "自定义":
|
||||||
self.show_custom_frame()
|
self.show_custom_frame()
|
||||||
|
# 更新比例显示为当前模板的比例
|
||||||
|
ratio_str = f"{self.current_template.ratio[0]}:{self.current_template.ratio[1]}"
|
||||||
|
self.ratio_var.set(ratio_str)
|
||||||
else:
|
else:
|
||||||
self.hide_custom_frame()
|
self.hide_custom_frame()
|
||||||
# 设置默认尺寸
|
if not (hasattr(self, '_loading_preset') and self._loading_preset):
|
||||||
w, h = map(int, self.ratio_var.get().split(":"))
|
try:
|
||||||
self.width_var.set(1920 if w > h else 1080)
|
w, h = map(int, self.ratio_var.get().split(":"))
|
||||||
self.height_var.set(int(self.width_var.get() * h / w))
|
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):
|
def show_custom_frame(self):
|
||||||
"""显示自定义尺寸框"""
|
"""显示自定义尺寸框"""
|
||||||
@ -190,52 +218,96 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
"""隐藏自定义尺寸框"""
|
"""隐藏自定义尺寸框"""
|
||||||
self.custom_frame.grid_forget()
|
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):
|
def choose_bg_image(self):
|
||||||
"""选择背景图"""
|
"""选择背景图"""
|
||||||
file_path = filedialog.askopenfilename(
|
file_path = filedialog.askopenfilename(
|
||||||
filetypes=[
|
title="选择背景图",
|
||||||
("图像文件", "*.jpg;*.jpeg;*.png;*.webp;*.bmp"),
|
filetypes=[("图片文件", "*.png *.jpg *.jpeg *.gif *.bmp")]
|
||||||
("所有文件", "*.*")
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
if file_path:
|
if file_path:
|
||||||
if self.current_template.load_background(file_path):
|
if self.current_template.load_background(file_path):
|
||||||
self.bg_image_var.set("已设置")
|
self.bg_image_var.set("已设置")
|
||||||
|
# 刷新主窗口画布
|
||||||
|
self.parent.get_canvas().draw_preview()
|
||||||
|
else:
|
||||||
|
messagebox.showerror("错误", "加载背景图失败")
|
||||||
|
|
||||||
def clear_bg_image(self):
|
def clear_bg_image(self):
|
||||||
"""清除背景图"""
|
"""清除背景图"""
|
||||||
self.current_template.clear_background()
|
self.current_template.clear_background()
|
||||||
self.bg_image_var.set("无")
|
self.bg_image_var.set("无")
|
||||||
|
# 刷新主窗口画布
|
||||||
|
self.parent.get_canvas().draw_preview()
|
||||||
|
|
||||||
def on_ok(self):
|
def on_ok(self):
|
||||||
"""确认按钮"""
|
"""确认按钮"""
|
||||||
# 如果选择了预设,则应用预设
|
# 只有在用户主动点击"加载"按钮加载预设时才应用预设
|
||||||
selected_preset = self.preset_var.get()
|
# 不再自动应用选中的预设
|
||||||
if selected_preset:
|
|
||||||
if not self.preset_manager.load_preset_to_template(selected_preset, self.current_template):
|
|
||||||
messagebox.showerror("错误", "加载预设失败")
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if self.ratio_var.get() == "自定义":
|
if self.ratio_var.get() == "自定义":
|
||||||
width = self.width_var.get()
|
try:
|
||||||
height = self.height_var.get()
|
width = self.width_var.get()
|
||||||
|
height = self.height_var.get()
|
||||||
|
except tk.TclError:
|
||||||
|
messagebox.showerror("错误", "请输入有效的整数")
|
||||||
|
return
|
||||||
if width <= 0 or height <= 0:
|
if width <= 0 or height <= 0:
|
||||||
messagebox.showerror("错误", "宽度和高度必须为正数")
|
messagebox.showerror("错误", "宽度和高度必须为正数")
|
||||||
return
|
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 = {
|
self.result = {
|
||||||
"type": "custom",
|
"type": "custom",
|
||||||
"width": width,
|
"width": width,
|
||||||
"height": height,
|
"height": height,
|
||||||
"bg_color": self.bg_color_var.get()
|
"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:
|
else:
|
||||||
w, h = map(int, self.ratio_var.get().split(":"))
|
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 = {
|
self.result = {
|
||||||
"type": "preset",
|
"type": "preset",
|
||||||
"ratio": (w, h),
|
"ratio": tuple([w, h]),
|
||||||
"width": self.width_var.get(),
|
"width": self.width_var.get(),
|
||||||
"bg_color": self.bg_color_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()
|
self.destroy()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -250,5 +322,23 @@ class TemplateDialog(tk.Toplevel):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,9 @@
|
|||||||
|
"""
|
||||||
|
作者:太一
|
||||||
|
微信:taiyi1224
|
||||||
|
邮箱:shuobo1224@qq.com
|
||||||
|
"""
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import cv2
|
import cv2
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user