特别声明:
1:接收最新文章代码,请点击下方并关注+收藏公众号!






“老板,公章怎么又丢了?”——别急着去派出所,先打开这款自定义印章生成器!它就像“公章版美图秀秀”:公司名字想换就换,五角星想歪就歪,颜色从姨妈红到基佬紫随你挑,甚至还能一键“做旧”,盖上去像 1998 年的老文件。全程鼠标点点,零代码基础的大爷大妈都能三分钟刻出十枚“公章”,然后……(咳)仅供学习测试,千万别去骗房东!好了,玩笑归玩笑,下面把代码拆成“乐高说明书”,一层层带你搭出这枚“数字印章”。
学完你能:
# 创建虚拟环境(可选)python -m venv seal_envsource seal_env/bin/activate # Win 用 seal_env\Scripts\activate# 安装依赖pip install -i https://pypi.tuna.tsinghua.edu.cn/simple \ pillow==10.0.1# tkinter 是 Python 标准库,无需额外安装;Linux 需 sudo apt-get install python3-tk验证:
>>> import tkinter, PIL, math, os>>> print("✅ 环境 OK")import tkinter as tkfrom tkinter import ttk, colorchooser, filedialog, messageboxfrom PIL import Image, ImageDraw, ImageFont, ImageTk, ImageOpsimport math, osclassSealGenerator:def__init__(self, root): self.root = root self.root.title("自定义印章生成工具") self.root.geometry("1000x750") self.root.resizable(True, True)# 1. 默认参数池(后续所有控件只改这里) self.seal_params = { … } # 见最上方源码# 2. 创建三大区域 self.main_frame = ttk.Frame(root, padding="10") self.main_frame.pack(fill=tk.BOTH, expand=True) self.create_preview_area() # 左侧 self.create_settings_area() # 右侧 self.create_bottom_area() # 底部# 3. 默认先画一次 self.generate_seal()代码解释
self.seal_params 字典,后续所有 trace_add 只改字典,再统一调用 generate_seal() 重绘。defcreate_preview_area(self): preview_frame = ttk.LabelFrame(self.main_frame, text="实时预览", padding="10") preview_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))# 4.1 缩放滑条 self.scale_var = tk.DoubleVar(value=1.0) scale = ttk.Scale(…, command=lambda v: self.update_preview_scale(float(v)))# 4.2 画布 & 标签 self.preview_canvas = tk.Canvas(preview_frame, width=300, height=300, bg="white") self.seal_label = ttk.Label(self.preview_canvas, style="White.TLabel") self.seal_label.place(relx=0.5, rely=0.5, anchor=tk.CENTER)代码解释
update_preview_scale 只做一件事:把 self.current_seal 按新尺寸 resize 后再包成 ImageTk.PhotoImage 塞回 label。label.image = tk_image 防止被垃圾回收,这是 Tkinter 的老坑。defcreate_settings_area(self): … canvas = tk.Canvas(scroll_frame) scrollbar = ttk.Scrollbar(scroll_frame, orient="vertical", command=canvas.yview) scrollable_frame = ttk.Frame(canvas) canvas.create_window((0, 0), window=scrollable_frame, anchor="nw") canvas.configure(yscrollcommand=scrollbar.set)代码解释
Canvas+Scrollbar 组合实现“滚轮自由”。self.left_column / right_column 两个 Frame 一次性 pack(side=tk.LEFT/RIGHT),层级清晰。以“公司设置”为例:
defcreate_company_settings(self): frame = ttk.LabelFrame(self.left_column, text="公司名称设置", padding="5") frame.pack(fill=tk.X, padx=5, pady=5)# 5.1 公司名称输入 self.company_name_var = tk.StringVar(value=self.seal_params["company_name"]) ttk.Entry(frame, textvariable=self.company_name_var, width=25).grid(row=0, column=1, pady=2) self.company_name_var.trace_add("write", lambda *args: self.on_setting_change())# 5.2 字体下拉 self.company_font_var = tk.StringVar(value=self.seal_params["company_font"]) font_combo = ttk.Combobox(frame, textvariable=self.company_font_var, values=self.font_families, state="readonly", width=22) font_combo.bind("<<ComboboxSelected>>", lambda *args: self.on_setting_change()) …代码解释
trace_add 或 bind 最终指向同一个回调 on_setting_change(),保证“任何控件动→字典更新→重绘”,逻辑单点维护。defgenerate_seal(self): size = self.seal_params["seal_size"] img = Image.new('RGBA', (size, size), (255, 255, 255, 0)) draw = ImageDraw.Draw(img)# 6.1 外圆 radius = size // 2 - self.seal_params["outer_border"] // 2 center = (size // 2, size // 2) draw.ellipse([center[0]-radius, center[1]-radius, center[0]+radius, center[1]+radius], outline=self.seal_params["main_color"], width=self.seal_params["outer_border"])# 6.2 内圆(可选)if self.seal_params["show_border"]: inner_radius = radius - 20 draw.ellipse([…], outline=…, width=…)# 6.3 环形公司名 company = self.seal_params["company_name"]if company: adj_radius = radius - 15 + self.seal_params["company_vertical_offset"] self.draw_circular_text(img, draw, company, center, adj_radius, …)# 6.4 底部章名 seal_name = self.seal_params["seal_name"]if seal_name: font = self.get_font(…) w, h = self.get_text_size(draw, seal_name, font) draw.text((center[0]-w//2, center[1]+radius//2+margin), seal_name, font=font, fill=color)# 6.5 中心五角星/文字 …类似上面# 6.6 老化if self.seal_params["use_aging"]: img = self.apply_aging_effect(img)# 保存到 self.current_seal 供下载 & 预览 self.current_seal = img self.update_preview_scale(self.preview_scale)代码解释
center 和 radius 计算,放大缩小只需改 seal_size,一键适配。defdraw_circular_text(self, img, draw, text, center, radius, font_family, font_size, bold, color, invert=False, char_spacing=0): font = self.get_font(font_family, font_size, bold) chars = list(text) num = len(chars)if num == 0: return# 7.1 计算总角度 base_angle = 180 spacing_factor = char_spacing / 5 total_angle = base_angle * (1 - min(0.8, spacing_factor)) start_angle = 90 + total_angle // 2 end_angle = 90 - total_angle // 2 angle_step = (start_angle - end_angle) / (num - 1) if num > 1else0for i, ch in enumerate(chars): angle = math.radians(start_angle - i * angle_step) x = center[0] + radius * math.cos(angle) y = center[1] - radius * math.sin(angle) char_angle = math.degrees(angle) + 90# 让字“立”在圆上# 7.2 单字符画到透明小图 ch_img = Image.new('RGBA', (font_size*2, font_size*2), (255,255,255,0)) ch_draw = ImageDraw.Draw(ch_img) ch_draw.text((font_size, font_size), ch, font=font, fill=color, anchor='mm')# 7.3 倒置(上下+左右镜像)if invert: ch_img = ImageOps.flip(ch_img) ch_img = ImageOps.mirror(ch_img)# 7.4 旋转 + 粘贴 rotated = ch_img.rotate(char_angle, expand=True) img.paste(rotated, (int(x-rotated.width//2), int(y-rotated.height//2)), rotated)代码解释
char_spacing 放大到 20 时,字与字之间会“散圈”,实现“稀疏公章”效果。defapply_aging_effect(self, img):import random width, height = img.size pixels = img.load()for i in range(width):for j in range(height):if random.random() < 0.02: # 2% 噪点 r, g, b, a = pixels[i, j]if a > 0: # 只污染非透明 gray = random.randint(50, 150) pixels[i, j] = (gray, gray, gray, a)return img代码解释
ImageOps.posterize 或 GaussianBlur 做旧纸张。defgenerate_chinese_seal(self): self.company_font_var.set("SimHei") self.main_color_var.set("#FF0000") self.on_setting_change()defgenerate_bilingual_seal(self): self.company_font_var.set("SimHei") self.main_color_var.set("#0000FF") self.on_setting_change()代码解释
defdownload_seal(self):ifnot hasattr(self, 'current_seal'):return file_path = filedialog.asksaveasfilename( defaultextension=".png", filetypes=[("PNG files", "*.png"), ("All files", "*.*")])if file_path:try: self.current_seal.save(file_path) messagebox.showinfo("保存成功", f"印章已保存到:\n{file_path}")except Exception as e: messagebox.showerror("保存失败", str(e))代码解释
defaultextension 自动补 .png,防止手滑保存成“无扩展名”。self.current_seal 原尺寸,不受预览缩放影响,保证打印 300dpi 不失真。__init__ | ||
generate_seal | ||
draw_circular_text | ||
draw.text | ||
apply_aging_effect | ||
download_seal | asksaveasfilename |
可继续完善的功能
PIL.ImageFilter 加高斯噪底纹,盖完章像真纸。arial.ttf,兼容大小写。pip install pyinstallerpyinstaller -F -w -i seal.ico seal_gui.py生成 seal_gui.exe,发给同事炫技。整篇代码 500+ 行,但层层拆分后就像“套娃”,每一层只关心自己的逻辑:
界面层→参数层→绘图层→特效层→导出层
你完全可以把“章”换成“头像”、“徽章”、“月饼模具”,套路一模一样。
最后彩蛋把 center_content 改成 “已验真”,main_color 改成 #00C853,一秒变成“绿色健康码”印章,盖在手背上出门买菜,小区保安都夸你硬核防疫!
(再次强调:本文仅供技术学习,非法用途后果自负。)
点击【关注+收藏】获取最新的实战代码案例
特别声明:
1:接收最新文章代码,请点击下方并关注+收藏公众号!
2:文章中的源码或者exe程序,非免费,源码+EXE程序=10元!
3:有源码需求的,请关注公众号并联系作者处获取源码!
Python实现中文图片文字处理器——让汉字“贴图”飞一会儿!
Python实现诊断证明书编辑器——从 0 到 1 的“土味”GUI 之旅
Python-Ai基于火山方舟&豆包API的全屏实时聊天应用
用Python打造汉字笔画查询工具:从GUI界面到笔顺动画实现
Python超实用 Markdown 转富文本神器 —— 代码全解析
【实战1】
【实战2】
【实战3】
【实战4】

