每个周末,我喜欢和户外俱乐部的小伙伴们一起到野外登山徒步,一晃有七、八个年头了。前些天受天行健户外聚乐部群主的委托,要给一批驴友用photoshop制作登顶纪念证书(图片),就是拿来给完成登顶的驴友们发发微信朋友圈的图片,同时顺带也给俱乐部做了广告。于是乎,我索性用python做了个小软件,这样用软件生成多省事,不用每次活动都要花时间PS了。
软件界面
源代码
certific.pyw
import pyautogui as pg import datetime as dt import tkinter as tk import tkinter.font as tkFont from PIL import Image,ImageTk,ImageGrab def winOpen(W,H): X,Y = pg.size() X0 = (X-W)//2 Y0 = (Y-H)//2 winSize = str(W)+'x'+str(H) winPos = winSize+'+'+str(X0)+'+'+str(Y0) win.geometry(winPos) win.resizable(False,False) win.wm_attributes('-topmost',True) wTitle = u'登顶纪念证书生成器' win.title(wTitle) initWidget() fillText() win.update() def initWidget(): global canvas,bgImg,et canvas = tk.Canvas(win,width=600,height=800,bg='white') canvas.place(x=0,y=0) image = Image.open('certific.png') bgImg = ImageTk.PhotoImage(image) canvas.create_image(300,400,image = bgImg) lbText=['线路:','证书:','姓名:','高峰:','简介:','日期:'] etText=['苏州·灵树线','登顶纪念证书','青荷莲子', '大阳山·箭阙峰','海拔:338米'] d = dt.date.today() strDate = '{0:04}.{1:02}.{2:02}'.format(d.year,d.month,d.day) etText.append(strDate) xLeft,yTop,yStep=630,50,60 etWidth=243 et,lb = [],[] for i in range(len(lbText)): et.append(0) et[i] = tk.Entry(win) et[i].place(x=xLeft,y=yTop+yStep*i,width=etWidth) et[i].insert(0,etText[i]) lb.append(0) lb[i] = tk.Label(win, text=lbText[i],anchor='w') lb[i].place(x=xLeft,y=yTop+yStep*i-26) bX,bY = 650,400 bTitle = u'内容修改' tBtn1 = tk.Button(win,text=bTitle,command=fillText) tBtn1.place(x=bX,y=bY,width=bW,height=bH) bX += 120 bTitle = u'生成证书' tBtn1 = tk.Button(win,text=bTitle,command=saveImage) tBtn1.place(x=bX,y=bY,width=bW,height=bH) bX,bY = 650,460 bTitle = u'导入名单' tBtn1 = tk.Button(win,text=bTitle,command=importList) tBtn1.place(x=bX,y=bY,width=bW,height=bH) bX += 120 bTitle = u'批量生成' tBtn1 = tk.Button(win,text=bTitle,command=batchCertific) tBtn1.place(x=bX,y=bY,width=bW,height=bH) def fillText(): global et,idText yTop = [55,110,305,490,540,725] font = [tkFont.Font(family='微软雅黑', size=25, weight='bold'), tkFont.Font(family='微软雅黑', size=35, weight='bold'), tkFont.Font(family='楷体', size=26), tkFont.Font(family='黑体', size=22), tkFont.Font(family='宋体', size=20), tkFont.Font(family='微软雅黑',size=18)] color = ['#33a3d0','#33a3d0','#6d6d6d', '#0ab193','#4cc580','#4cc580'] count = len(yTop) try: for i in range(count): canvas.itemconfig(idText[i],text=et[i].get(),fill=color[i]) except: idText = [0]*count for i in range(count): idText[i] = canvas.create_text(300,yTop[i], anchor='center',font=font[i],text=et[i].get(),fill=color[i]) def grabImage(widget, filename): widget.update() x = win.winfo_rootx()+widget.winfo_x()+1 y = win.winfo_rooty()+widget.winfo_y()+1 w = widget.winfo_width()-4 h = widget.winfo_height()-4 box = (x, y, x+w, y+h) ImageGrab.grab().crop(box).save(filename) def saveImage(): global et grabImage(canvas,et[5].get()+et[0].get()+'·'+et[2].get()+'.png') def importList(): pass def batchCertific(): pass if __name__ == '__main__': win = tk.Tk() wW,wH = 900,800 #窗体的宽高 bW,bH = 90,40 #按钮的宽高 winOpen(wW,wH) win.mainloop()
空白证书
certific.png,可以根据需要制作自己的“空白证书”图片:
成品证书
图片宽高: 600x800;大小约200Kb
编译软件
保存源文件 certific.png 和空白证书的图片 certific.png 到D盘根目录,再找一个好看的程序图标文件favicon.ico。使用以下编译命令:
pyinstaller --onefile --windowed --icon="D:\favicon.ico" certific.pyw
编译过程:
D:\>pyinstaller --onefile --windowed --icon="D:\favicon.ico" certific.pyw 486 INFO: PyInstaller: 4.5.1 487 INFO: Python: 3.8.8 487 INFO: Platform: Windows-7-6.1.7601-SP1 495 INFO: wrote D:\certific.spec 500 INFO: UPX is not available. 。。。省略N行 。。。 46234 INFO: checking EXE 46234 INFO: Building EXE because EXE-00.toc is non existent 46235 INFO: Building EXE from EXE-00.toc 46313 INFO: Copying icons from ['D:\\favicon.ico'] 46315 INFO: Writing RT_GROUP_ICON 0 resource with 20 bytes 46316 INFO: Writing RT_ICON 1 resource with 4264 bytes 46330 INFO: Updating manifest in D:\build\certific\runw.exe.6n17h0bd 46332 INFO: Updating resource type 24 name 1 language 0 46337 INFO: Appending archive to EXE D:\dist\certific.exe 55621 INFO: Building EXE from EXE-00.toc completed successfully. D:\>
编译完成后,在 D:\dist\ 文件夹下找到可执行文件 certific.exe,一定和certific.png放在同一文件夹下才能正常运行。
后续
导入清单和批量生成的代码没有写进去