【Python】Tkinter 程序设置窗口图标并容灾处理
前言
众所周知,Python Tkinter 程序的窗口默认图标为一篇蓝色羽毛,但是如何替换这张默认图,让自己的程序更有特色,本文会给出答案。
前提:假设有一张需要设置为图标(ico 格式,非该格式请转换)的图片:favicon.ico
。
正文
基本框架和已知问题
其实网上有很多教程的,但是今天我的教程更多的是总结,还有一个重要的内容:容灾处理。
先给大家看看最初始化的代码:
from tkinter import *
window = Tk()
window.title("极客藏源")
# 核心代码 ↓
window.iconbitmap('favicon.ico')
# 核心代码 ↑
# 让窗口居中
sw = window.winfo_screenwidth()
sh = window.winfo_screenheight()
ww = 800
wh = 600
x = (sw-ww) / 2
y = (sh-wh) / 2
window.geometry("%dx%d+%d+%d" % (ww, wh, x, y))
# 设置禁止用户手动改动窗口宽高
window.resizable(False, False)
# 开始主循环
window.mainloop()
运行效果:
看上去,图标好像确实被改了,但是大家注意,Tk().iconbitmap
方法传入的参数是一个文件名。也就是如果我删除了这个图标文件,那么:
Traceback (most recent call last):
File "c:\Users\asus\Desktop\sale\test\main.py", line 6, in <module>
window.iconbitmap('favicon.ico')
File "C:\Users\asus\AppData\Local\Programs\Python\Python311\Lib\tkinter\__init__.py", line 2136, in wm_iconbitmap
return self.tk.call('wm', 'iconbitmap', self._w, bitmap)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
_tkinter.TclError: bitmap "favicon.ico" not defined
尔等可知不做容灾处理的危害性?毕竟打包成 exe 文件也是这样。因为这个图标文件程序只负责记住了文件名,所以打包时并不会封装这张图片。因此如果把图标一删,程序就打不开了。这在那些手欠的电脑小白那里准出事。那么怎么应对这种情况的出现呢?
其实我们完全可以让程序内存一个图标可还原形式(如 Base64 编码),然后在读取不到的时候将其还原出来后再设置图标。
注意:这里为什么不说打包利用其它工具将成品打包成单文件呢?这样不是完美解决问题了吗?解决了个毛线!这样二次打包的成品,其实也就是在某个你不知道的位置解压出一个目录然后再运行(关闭后会删除)。如果你的程序设计数据的生成,那么告诉你,你不会在你预定的位置看到文件操作结果(排除绝对目录),因为此时的单文件程序只会在临时文件夹里操作,关闭后,这个临时文件夹就被删除了。
生成图标的编码数据
我们利用 Python 自带库 base64
帮我们完成这个任务。
首先创建一个临时 Python 脚本文件,保持图标文件与其在同一个目录内,然后在这个脚本文件里面输入以下代码并运行:
from base64 import b64encode as a
with open('favicon.ico', 'rb') as f:
code = a(f.read())
with open('fav.py', 'a', encoding='utf-8') as g:
g.write("icon = " + repr(code))
运行这个文件后,你将会得到一个名为 fav.py
的脚本文件。接下来我们将其作为模块使用。
解惑:为何这样可以避免错误?因为打包时所用的模块都会被一起编译和打包。
重写相关的核心代码
返回主程序文件,改写代码。
--snip--
# 核心代码 ↓
try:
window.iconbitmap('favicon.ico')
except:
from fav import icon
from base64 import b64decode as a
with open('favicon.ico', 'wb') as f:
f.write(a(icon))
window.iconbitmap('favicon.ico')
# 核心代码 ↑
--snip--
运行和打包后的效果
上面代码已经告诉我们了:首先碰错,不出错(图标存在)就万事大吉,直接设图标;出错就还原图标(保存在程序目录)再设置图标。
这点小事,不用我赘述了。
末
望解君忧。