Python圆形印章生成工具 使用文档
圆形印章生成工具 使用文档

学在坚持公众号 出品
工具简介
圆形印章生成工具提供两种使用方式:
-
Python 桌面版( 圆形印章生成工具.py):基于 Tkinter + Pillow,支持 4 倍超采样高清渲染 -
H5 网页版( 圆形印章生成工具.html):纯前端 Canvas 实现,双击即可在浏览器中使用,无需安装任何依赖
两个版本功能一致:可视化制作中文/中英文圆形公章,支持全参数自定义、各元素可拖动调整位置、实时预览、一键下载透明底印章图片。
版本对比
|
|
|
|
|---|---|---|
|
|
python 圆形印章生成工具.py |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
快速开始
Python 桌面版
pip install Pillowpython 圆形印章生成工具.py
H5 网页版
直接双击 圆形印章生成工具.html 文件,在浏览器中打开即可使用。
界面布局
两个版本均采用左右分栏布局:
-
左侧(40%):参数配置面板,带滚动条 -
右侧(60%):印章实时预览区,支持鼠标拖动各元素
拖动功能说明
右侧预览区的印章各元素可以直接用鼠标拖动调整位置:
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
拖动时左侧对应参数值会实时同步更新。点击”重置拖动位置”可恢复默认。
参数配置详解
1. 公司名称(外圈弧形文字)
沿印章外圈弧形排列的主体文字。
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2. 章名(下方居中文字)
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
3. 中心内容(印章中心图案)
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
4. 防伪码(底部弧形文字)
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5. 边框设置
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
6. 外观与尺寸
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
操作流程
1. 打开工具(Python版运行py / H5版双击html) ↓2. 左侧面板调整参数(或右侧直接拖动元素) ↓3. 实时预览自动更新 ↓4. 满意后点击"下载印章"保存 PNG 文件
输出格式
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
功能按钮
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
项目文件
圆形印章生成工具.py # Python 桌面版(Tkinter GUI)圆形印章生成工具.html # H5 网页版(纯前端 Canvas)圆形印章生成工具.md # 本文档
Python 版代码架构
|
|
|
|---|---|
|
|
|
|
|
|
|
|
|
H5 版技术栈
-
纯 HTML + CSS + JavaScript -
Canvas 2D API 绘制印章 -
鼠标事件实现拖动 -
toDataURL()导出 PNG
常见问题
Q: Python 版字体显示不正确?
A: 确保 Windows 系统已安装宋体、黑体、楷体等字体(系统自带)。
Q: H5 版字体和 Python 版不一样?
A: H5 版使用浏览器字体渲染,效果可能略有差异,但功能一致。
Q: 文字重叠怎么办?
A: 调整字间距、字边距或字号,或直接拖动元素调整位置。
Q: 如何去掉防伪码?
A: 将防伪码的”内容”清空即可。
Q: 参数有上限吗?
A: 没有最大上限,可以自由输入任意数值。
注意事项
-
本工具仅供学习和演示用途,请勿用于制作伪造公章等违法行为 -
生成的印章为模拟效果,不具有法律效力 -
Python 版建议在 Windows 系统下使用以获得最佳字体支持 -
H5 版建议使用 Chrome / Edge / Firefox 等现代浏览器
版本信息
-
版本:2.0.0 -
作者:学在坚持公众号 -
Python 版:Tkinter + Pillow -
H5 版:HTML5 Canvas -
许可证:MIT License
"""圆形印章生成工具 - 学在坚持公众号功能:可视化制作中文/中英文圆形公章,支持全参数自定义,一键生成透明底印章图片并下载"""import tkinter as tkfrom tkinter import ttk, colorchooser, filedialog, messageboxfrom PIL import Image, ImageDraw, ImageFontimport mathimport osimport randomclass SealGenerator:"""圆形印章生成器核心类"""def __init__(self):self.size = 240self.color = (255, 0, 0)self.image = Nonedef create_seal(self, params):"""根据参数生成印章图片"""self.size = params['seal_size']self.color = params['seal_color']scale = 4img_size = self.size * scaleimg = Image.new('RGBA', (img_size, img_size), (255, 255, 255, 0))draw = ImageDraw.Draw(img)center = img_size // 2radius = (img_size - 20 * scale) // 2border_width = params['outer_border'] * scaledraw.ellipse([center - radius, center - radius, center + radius, center + radius],outline=self.color + (255,), width=border_width)if params['inner_border_show']:inner_border_width = params['inner_border'] * scaleinner_radius = radius - (border_width + 2 * scale)draw.ellipse([center - inner_radius, center - inner_radius,center + inner_radius, center + inner_radius],outline=self.color + (255,), width=inner_border_width)self._draw_arc_text_top(img, draw, center, radius, params, scale)self._draw_center_content(img, draw, center, params, scale)self._draw_bottom_text(img, draw, center, params, scale)self._draw_arc_text_bottom(img, draw, center, radius, params, scale)if params.get('aging_effect', False):img = self._apply_aging(img, scale)img = img.resize((self.size, self.size), Image.LANCZOS)self.image = imgreturn imgdef _get_font(self, font_name, size, bold=False):"""获取字体"""font_map = {'宋体': 'simsun.ttc','黑体': 'simhei.ttf','楷体': 'simkai.ttf','仿宋': 'simfang.ttf','微软雅黑': 'msyh.ttc','Arial': 'arial.ttf',}font_file = font_map.get(font_name, 'simsun.ttc')paths = [f"C:/Windows/Fonts/{font_file}",f"/usr/share/fonts/truetype/{font_file}",font_file]for path in paths:if os.path.exists(path):try:return ImageFont.truetype(path, size)except:passtry:return ImageFont.truetype("C:/Windows/Fonts/simsun.ttc", size)except:return ImageFont.load_default()def _draw_arc_text_top(self, img, draw, center, radius, params, scale):"""绘制顶部弧形文字"""text = params['company_name']if not text:returnfont_size = params['company_font_size'] * scalefont = self._get_font(params['company_font'], font_size, params['company_bold'])spacing = params['company_spacing'] * scalemargin = params['company_margin'] * scaletext_radius = radius - margin - font_size // 2 - 10 * scalechar_angles = []total_angle = 0for char in text:bbox = font.getbbox(char)char_width = bbox[2] - bbox[0]angle = (char_width + spacing) / text_radiuschar_angles.append(angle)total_angle += anglestart_angle = -math.pi / 2 - total_angle / 2current_angle = start_anglefor i, char in enumerate(text):angle = current_angle + char_angles[i] / 2x = center + text_radius * math.cos(angle)y = center + text_radius * math.sin(angle)char_img = Image.new('RGBA', (font_size * 2, font_size * 2), (0, 0, 0, 0))char_draw = ImageDraw.Draw(char_img)bbox = font.getbbox(char)cw = bbox[2] - bbox[0]ch = bbox[3] - bbox[1]char_draw.text((font_size - cw // 2, font_size - ch // 2),char, font=font, fill=self.color + (255,))rotation = -math.degrees(angle + math.pi / 2)char_img = char_img.rotate(rotation, resample=Image.BICUBIC, expand=False)img.paste(char_img, (int(x - font_size), int(y - font_size)), char_img)current_angle += char_angles[i]def _draw_center_content(self, img, draw, center, params, scale):"""绘制中心内容"""text = params['center_content']if not text:returnfont_size = params['center_font_size'] * scalefont = self._get_font(params['center_font'], font_size, params['center_bold'])offset_y = params['center_offset_y'] * scaleoffset_x = params['center_offset_x'] * scalebbox = font.getbbox(text)tw = bbox[2] - bbox[0]th = bbox[3] - bbox[1]x = center - tw // 2 + offset_xy = center - th // 2 + offset_ydraw.text((x, y), text, font=font, fill=self.color + (255,))def _draw_bottom_text(self, img, draw, center, params, scale):"""绘制下方章名"""text = params['seal_name']if not text:returnfont_size = params['name_font_size'] * scalefont = self._get_font(params['name_font'], font_size, params['name_bold'])offset_y = params['name_offset_y'] * scaleoffset_x = params['name_offset_x'] * scalebbox = font.getbbox(text)tw = bbox[2] - bbox[0]x = center - tw // 2 + offset_xy = center + font_size + offset_ydraw.text((x, y), text, font=font, fill=self.color + (255,))def _draw_arc_text_bottom(self, img, draw, center, radius, params, scale):"""绘制底部弧形防伪码"""text = params['code_text']if not text:returnfont_size = params['code_font_size'] * scalefont = self._get_font(params['code_font'], font_size, params['code_bold'])spacing = params['code_spacing'] * scalemargin = params['code_margin'] * scalecorrection = params['code_correction'] * scaletext_radius = radius - margin - font_size // 2 - 10 * scalechar_angles = []total_angle = 0for char in text:bbox = font.getbbox(char)char_width = bbox[2] - bbox[0]angle = (char_width + spacing) / text_radiuschar_angles.append(angle)total_angle += anglestart_angle = math.pi / 2 - total_angle / 2current_angle = start_anglefor i, char in enumerate(text):angle = current_angle + char_angles[i] / 2x = center + text_radius * math.cos(angle)y = center + text_radius * math.sin(angle) + correctionchar_img = Image.new('RGBA', (font_size * 2, font_size * 2), (0, 0, 0, 0))char_draw = ImageDraw.Draw(char_img)bbox = font.getbbox(char)cw = bbox[2] - bbox[0]ch = bbox[3] - bbox[1]char_draw.text((font_size - cw // 2, font_size - ch // 2),char, font=font, fill=self.color + (255,))rotation = -math.degrees(angle - math.pi / 2)char_img = char_img.rotate(rotation, resample=Image.BICUBIC, expand=False)img.paste(char_img, (int(x - font_size), int(y - font_size)), char_img)current_angle += char_angles[i]def _apply_aging(self, img, scale):"""应用老化效果"""pixels = img.load()width, height = img.sizefor _ in range(int(width * height * 0.03)):x = random.randint(0, width - 1)y = random.randint(0, height - 1)if pixels[x, y][3] > 0:pixels[x, y] = (0, 0, 0, 0)for _ in range(int(width * height * 0.005)):x = random.randint(0, width - 1)y = random.randint(0, height - 1)if pixels[x, y][3] == 0:r, g, b = self.colorpixels[x, y] = (r, g, b, random.randint(30, 100))return imgdef save_image(self, filepath):"""保存印章图片"""if self.image:self.image.save(filepath, 'PNG')return Truereturn Falseclass DraggablePreview:"""可拖动预览画布 - 支持各元素独立拖动"""def __init__(self, canvas, app):self.canvas = canvasself.app = appself.canvas_size = 420self.preview_size = 380self._dragging = Noneself._drag_start = Noneself.canvas.bind('<ButtonPress-1>', self._on_press)self.canvas.bind('<B1-Motion>', self._on_drag)self.canvas.bind('<ButtonRelease-1>', self._on_release)self.canvas.bind('<Motion>', self._on_hover)def _get_element_at(self, x, y):"""判断鼠标位置对应哪个可拖动元素"""cx = self.canvas_size // 2cy = self.canvas_size // 2rx = x - cxry = y - cyradius = self.preview_size // 2dist = math.sqrt(rx * rx + ry * ry)if dist > radius:return Noneif dist < radius * 0.25:return 'center'if radius * 0.25 <= dist < radius * 0.55 and ry > 0:return 'name'if dist >= radius * 0.55 and ry < 0:return 'company'if dist >= radius * 0.55 and ry > 0:return 'code'return 'center'def _on_hover(self, event):element = self._get_element_at(event.x, event.y)self.canvas.config(cursor='fleur' if element else '')def _on_press(self, event):self._dragging = self._get_element_at(event.x, event.y)if self._dragging:self._drag_start = (event.x, event.y)def _on_drag(self, event):if not self._dragging or not self._drag_start:returndx = event.x - self._drag_start[0]dy = event.y - self._drag_start[1]self._drag_start = (event.x, event.y)seal_size = self.app.seal_size.get()scale = seal_size / self.preview_sizeif self._dragging == 'center':self.app.center_offset_x.set(self.app.center_offset_x.get() + int(dx * scale))self.app.center_offset_y.set(self.app.center_offset_y.get() + int(dy * scale))elif self._dragging == 'name':self.app.name_offset_x.set(self.app.name_offset_x.get() + int(dx * scale))self.app.name_offset_y.set(self.app.name_offset_y.get() + int(dy * scale))elif self._dragging == 'company':self.app.company_margin.set(self.app.company_margin.get() + int(dy * scale))elif self._dragging == 'code':self.app.code_margin.set(self.app.code_margin.get() - int(dy * scale))def _on_release(self, event):self._dragging = Noneself._drag_start = Noneclass SealApp:"""印章生成工具GUI界面 - 学在坚持公众号"""def __init__(self):self.root = tk.Tk()self.root.title("圆形印章生成工具 - 学在坚持公众号")self.root.geometry("1100x750")self.root.resizable(True, True)self.generator = SealGenerator()self.seal_color = (255, 0, 0)self.preview_image = Noneself._create_ui()self._generate_preview()def _create_ui(self):"""创建界面 - 左右grid对半布局,右侧更大"""main_frame = ttk.Frame(self.root, padding=10)main_frame.pack(fill=tk.BOTH, expand=True)# 左侧40%,右侧60%main_frame.columnconfigure(0, weight=2)main_frame.columnconfigure(1, weight=3)main_frame.rowconfigure(0, weight=1)# 左侧参数面板left_frame = ttk.LabelFrame(main_frame, text="参数配置", padding=5)left_frame.grid(row=0, column=0, sticky='nsew', padx=(0, 5))canvas = tk.Canvas(left_frame)scrollbar = ttk.Scrollbar(left_frame, orient="vertical", command=canvas.yview)self.params_frame = ttk.Frame(canvas)self.params_frame.bind("<Configure>",lambda e: canvas.configure(scrollregion=canvas.bbox("all")))canvas.create_window((0, 0), window=self.params_frame, anchor="nw")canvas.configure(yscrollcommand=scrollbar.set)canvas.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)scrollbar.pack(side=tk.RIGHT, fill=tk.Y)def _on_mousewheel(event):canvas.yview_scroll(int(-1 * (event.delta / 120)), "units")canvas.bind_all("<MouseWheel>", _on_mousewheel)# 右侧预览面板(更大,可拖动)right_frame = ttk.LabelFrame(main_frame, text="印章预览 - 学在坚持公众号(可拖动各元素调整位置)", padding=10)right_frame.grid(row=0, column=1, sticky='nsew', padx=(5, 0))self.preview_canvas = tk.Canvas(right_frame, width=420, height=420, bg='white',highlightthickness=1, highlightbackground='#ccc')self.preview_canvas.pack(pady=10, anchor='center')# 拖动提示ttk.Label(right_frame,text="拖动:上半外圈=公司名称 | 中心=五角星 | 中下=章名 | 下半外圈=防伪码",foreground='#666').pack(pady=5)# 按钮区域btn_frame = ttk.Frame(right_frame)btn_frame.pack(fill=tk.X, pady=10, padx=40)ttk.Button(btn_frame, text="生成中文印章", command=self._generate_chinese).pack(fill=tk.X, pady=4)ttk.Button(btn_frame, text="生成中英文印章", command=self._generate_bilingual).pack(fill=tk.X, pady=4)ttk.Button(btn_frame, text="下载印章", command=self._download_seal).pack(fill=tk.X, pady=4)ttk.Button(btn_frame, text="重置拖动位置", command=self._reset_drag).pack(fill=tk.X, pady=4)self._create_params()# 初始化拖动功能self.draggable = DraggablePreview(self.preview_canvas, self)def _reset_drag(self):"""重置拖动位置"""self.center_offset_x.set(0)self.center_offset_y.set(0)self.name_offset_x.set(0)self.name_offset_y.set(-16)self.company_margin.set(0)self.code_margin.set(0)def _create_params(self):"""创建参数配置区域"""row = 0row = self._create_section_header("1. 公司名称(外圈弧形文字)", row)self.company_name = tk.StringVar(value="学在坚持圆形印章科技有限公司")row = self._create_entry("内容:", self.company_name, row)self.company_font = tk.StringVar(value="宋体")row = self._create_combo("字体:", self.company_font, ['宋体', '黑体', '楷体', '仿宋', '微软雅黑'], row)self.company_font_size = tk.IntVar(value=20)row = self._create_spinbox("字号:", self.company_font_size, 8, 99999, row)self.company_bold = tk.BooleanVar(value=True)row = self._create_check("加粗:", self.company_bold, row)self.company_spacing = tk.IntVar(value=0)row = self._create_spinbox("字间距:", self.company_spacing, -100, 99999, row)self.company_margin = tk.IntVar(value=0)row = self._create_spinbox("字边距:", self.company_margin, -100, 99999, row)row = self._create_section_header("2. 章名(下方居中文字)", row)self.seal_name = tk.StringVar(value="专用章")row = self._create_entry("内容:", self.seal_name, row)self.name_font = tk.StringVar(value="宋体")row = self._create_combo("字体:", self.name_font, ['宋体', '黑体', '楷体', '仿宋', '微软雅黑'], row)self.name_font_size = tk.IntVar(value=16)row = self._create_spinbox("字号:", self.name_font_size, 8, 99999, row)self.name_bold = tk.BooleanVar(value=True)row = self._create_check("加粗:", self.name_bold, row)self.name_offset_y = tk.IntVar(value=-16)row = self._create_spinbox("上下距离:", self.name_offset_y, -99999, 99999, row)self.name_offset_x = tk.IntVar(value=0)row = self._create_spinbox("左右距离:", self.name_offset_x, -99999, 99999, row)row = self._create_section_header("3. 中心内容(印章中心图案)", row)self.center_content = tk.StringVar(value="★")row = self._create_entry("内容:", self.center_content, row)self.center_font = tk.StringVar(value="宋体")row = self._create_combo("字体:", self.center_font, ['宋体', '黑体', '楷体', '仿宋', '微软雅黑'], row)self.center_font_size = tk.IntVar(value=50)row = self._create_spinbox("字号:", self.center_font_size, 10, 99999, row)self.center_bold = tk.BooleanVar(value=True)row = self._create_check("加粗:", self.center_bold, row)self.center_offset_y = tk.IntVar(value=0)row = self._create_spinbox("上下距离:", self.center_offset_y, -99999, 99999, row)self.center_offset_x = tk.IntVar(value=0)row = self._create_spinbox("左右距离:", self.center_offset_x, -99999, 99999, row)row = self._create_section_header("4. 防伪码(底部弧形文字)", row)self.code_text = tk.StringVar(value="1234567890123")row = self._create_entry("内容:", self.code_text, row)self.code_font = tk.StringVar(value="楷体")row = self._create_combo("字体:", self.code_font, ['宋体', '黑体', '楷体', '仿宋', '微软雅黑', 'Arial'], row)self.code_font_size = tk.IntVar(value=10)row = self._create_spinbox("字号:", self.code_font_size, 6, 99999, row)self.code_bold = tk.BooleanVar(value=True)row = self._create_check("加粗:", self.code_bold, row)self.code_spacing = tk.IntVar(value=0)row = self._create_spinbox("字间距:", self.code_spacing, -100, 99999, row)self.code_correction = tk.IntVar(value=0)row = self._create_spinbox("矫正:", self.code_correction, -99999, 99999, row)self.code_margin = tk.IntVar(value=0)row = self._create_spinbox("字边距:", self.code_margin, -100, 99999, row)row = self._create_section_header("5. 边框设置", row)self.outer_border = tk.IntVar(value=2)row = self._create_spinbox("外边线粗细:", self.outer_border, 1, 99999, row)self.inner_border = tk.IntVar(value=1)row = self._create_spinbox("内边线粗细:", self.inner_border, 1, 99999, row)self.inner_border_show = tk.BooleanVar(value=True)row = self._create_check("内边线显示:", self.inner_border_show, row)row = self._create_section_header("6. 外观与尺寸", row)color_frame = ttk.Frame(self.params_frame)color_frame.grid(row=row, column=0, columnspan=3, sticky='w', pady=2)ttk.Label(color_frame, text="印章颜色:").pack(side=tk.LEFT)self.color_btn = tk.Button(color_frame, text=" ", bg='#FF0000', width=4, command=self._choose_color)self.color_btn.pack(side=tk.LEFT, padx=5)self.color_label = ttk.Label(color_frame, text="#FF0000")self.color_label.pack(side=tk.LEFT)row += 1self.seal_size = tk.IntVar(value=240)row = self._create_spinbox("印章尺寸(px):", self.seal_size, 50, 99999, row)self.aging_effect = tk.BooleanVar(value=False)row = self._create_check("印章老化效果:", self.aging_effect, row)def _create_section_header(self, text, row):ttk.Separator(self.params_frame, orient='horizontal').grid(row=row, column=0, columnspan=3, sticky='ew', pady=(10, 5))row += 1ttk.Label(self.params_frame, text=text, font=('', 10, 'bold')).grid(row=row, column=0, columnspan=3, sticky='w', pady=(0, 5))row += 1return rowdef _create_entry(self, label, var, row):ttk.Label(self.params_frame, text=label).grid(row=row, column=0, sticky='w', pady=2)ttk.Entry(self.params_frame, textvariable=var, width=30).grid(row=row, column=1, columnspan=2, sticky='w', pady=2)var.trace_add('write', lambda *args: self._on_param_change())return row + 1def _create_combo(self, label, var, values, row):ttk.Label(self.params_frame, text=label).grid(row=row, column=0, sticky='w', pady=2)ttk.Combobox(self.params_frame, textvariable=var, values=values, width=12, state='readonly').grid(row=row, column=1, sticky='w', pady=2)var.trace_add('write', lambda *args: self._on_param_change())return row + 1def _create_spinbox(self, label, var, from_, to, row):ttk.Label(self.params_frame, text=label).grid(row=row, column=0, sticky='w', pady=2)ttk.Spinbox(self.params_frame, textvariable=var, from_=from_, to=to, width=8).grid(row=row, column=1, sticky='w', pady=2)var.trace_add('write', lambda *args: self._on_param_change())return row + 1def _create_check(self, label, var, row):ttk.Label(self.params_frame, text=label).grid(row=row, column=0, sticky='w', pady=2)ttk.Checkbutton(self.params_frame, variable=var).grid(row=row, column=1, sticky='w', pady=2)var.trace_add('write', lambda *args: self._on_param_change())return row + 1def _choose_color(self):color = colorchooser.askcolor(initialcolor='#%02x%02x%02x' % self.seal_color, title="选择印章颜色")if color[0]:self.seal_color = tuple(int(c) for c in color[0])self.color_btn.configure(bg=color[1])self.color_label.configure(text=color[1].upper())self._on_param_change()def _on_param_change(self, *args):if hasattr(self, '_render_job'):self.root.after_cancel(self._render_job)self._render_job = self.root.after(200, self._do_render)def _do_render(self):try:params = self._get_params()img = self.generator.create_seal(params)self._update_preview(img)except:passdef _get_params(self):return {'company_name': self.company_name.get(),'company_font': self.company_font.get(),'company_font_size': self.company_font_size.get(),'company_bold': self.company_bold.get(),'company_spacing': self.company_spacing.get(),'company_margin': self.company_margin.get(),'seal_name': self.seal_name.get(),'name_font': self.name_font.get(),'name_font_size': self.name_font_size.get(),'name_bold': self.name_bold.get(),'name_offset_y': self.name_offset_y.get(),'name_offset_x': self.name_offset_x.get(),'center_content': self.center_content.get(),'center_font': self.center_font.get(),'center_font_size': self.center_font_size.get(),'center_bold': self.center_bold.get(),'center_offset_y': self.center_offset_y.get(),'center_offset_x': self.center_offset_x.get(),'code_text': self.code_text.get(),'code_font': self.code_font.get(),'code_font_size': self.code_font_size.get(),'code_bold': self.code_bold.get(),'code_spacing': self.code_spacing.get(),'code_correction': self.code_correction.get(),'code_margin': self.code_margin.get(),'outer_border': self.outer_border.get(),'inner_border': self.inner_border.get(),'inner_border_show': self.inner_border_show.get(),'seal_color': self.seal_color,'seal_size': self.seal_size.get(),'aging_effect': self.aging_effect.get(),}def _generate_preview(self):try:params = self._get_params()img = self.generator.create_seal(params)self._update_preview(img)except Exception as e:messagebox.showerror("错误", f"生成印章失败:{str(e)}")def _generate_chinese(self):self._generate_preview()messagebox.showinfo("成功", "中文印章已生成,可点击[下载印章]保存")def _generate_bilingual(self):self._generate_preview()messagebox.showinfo("成功", "中英文印章已生成,可点击[下载印章]保存")def _update_preview(self, img):from PIL import ImageTkpreview_size = 380img_resized = img.resize((preview_size, preview_size), Image.LANCZOS)bg = Image.new('RGBA', (preview_size, preview_size), (255, 255, 255, 255))bg.paste(img_resized, (0, 0), img_resized)self.preview_image = ImageTk.PhotoImage(bg)self.preview_canvas.delete("all")self.preview_canvas.create_image(210, 210, image=self.preview_image)def _download_seal(self):if not self.generator.image:self._do_render()filepath = filedialog.asksaveasfilename(title="保存印章", defaultextension=".png",filetypes=[("PNG图片", "*.png"), ("所有文件", "*.*")],initialfile="印章.png")if filepath:if self.generator.save_image(filepath):messagebox.showinfo("成功", f"印章已保存到:\n{filepath}")else:messagebox.showerror("错误", "保存失败")def run(self):self.root.mainloop()if name == 'main':app = SealApp()app.run()
夜雨聆风