需求
工作环境每天都在变动,需要频繁连接不同的WiFi或其他网络,所以经常需要查看本机IP,希望有个程序能常驻托盘区域,点击就能查看IP。网上找的程序要么功能过多体积巨大,要么不满足需求,所以决定自己开发一个。
开发过程
作为一个自己的小需求,就不分析了,直接用自己熟悉的 python+pyinstaller
,不会的问 kimi
(AI好强大啊)。
需要的库
pillow
用于创建托盘图标psutil
用于获取网卡信息pyinstaller
用于打包成独立exe
使用pystray
本文功能实现的核心依赖,托盘功能库plyer
原本此库用来显示Windows通知,我需求是希望单击图标,Windows通知直接显示IP,结果我的电脑中【虚拟机】、【docker】、【蓝牙】、【WiFi】、【本地连接】之类的网卡加起来七八个,而Windows通知只能显示4行且最多256个字符,所以放弃这种方式
库安装
pip install pillow psutil pyinstaller pystray
代码
import pystray
from PIL import Image, ImageDraw
import psutil
import socket
def get_ip_addresses():
net_info = psutil.net_if_addrs()
ip_addresses = []
for interface, addrs in net_info.items():
# 过滤掉本地回环地址,因为我们都知道它是固定的127.0.0.1
if 'Loop' in interface:
continue
#VMware虚拟机的网卡名称太长了,截取成VMnet1和VMnet8
if 'VMware Network Adapter ' in interface:
interface = interface.replace('VMware Network Adapter ','')
for addr in addrs:
# 过滤掉IPv6,只显示IPv4,我自己bing搜了一下,socket.AF_INET是IPv4的常量,当然你直接写成数字2也没问题
if addr.family == socket.AF_INET:
ip_addresses.append(f"{interface}: {addr.address}")
return ip_addresses
# 创建托盘图标,kimi默认生成的像樱花国旗,懒得改了,就让它天天听我使唤吧!
def create_image(width, height, color):
image = Image.new('RGB', (width, height), color)
dc = ImageDraw.Draw(image)
dc.ellipse((width//4, height//4, width*3//4, height*3//4), fill=(255, 0, 0))
return image
def update_menu(icon):
# 获取最新的 IP 地址信息
ip_addresses = get_ip_addresses()
# 创建新的菜单项列表
menu_items = [pystray.MenuItem(ip, None) for ip in ip_addresses]
# 添加刷新按钮,点击刷新后托盘就关掉了,需要重新右击查看结果,搜了一下没找到点刷新不关闭直接刷新结果的方法,如果阅读到这里的你有什么好方法还望不吝赐教。
menu_items.append(pystray.MenuItem("刷新", lambda icon, item: update_menu(icon)))
# 要打包成独立exe运行就添加退出按钮,比较方便,不要去任务管理器手动结束任务了
menu_items.append(pystray.MenuItem("退出", lambda icon, item: icon.stop()))
# 更新托盘图标的菜单
icon.menu = pystray.Menu(*menu_items)
def on_clicked(icon, item):
# 本想着左键点击也能弹出,结果搜了半天还要增加这库那库,一看就占用很大体积,所以直接放弃了,这个方法好像没啥用,不要也行
# 如果点击的是托盘图标本身,显示菜单
if item is None:
icon.menu.show(icon)
# 创建托盘图标
icon = pystray.Icon("network_icon", create_image(64, 64, "white"), "网卡 IP 地址")
# 初始更新菜单项
update_menu(icon)
# 设置点击事件
icon.on_clicked = on_clicked
# 运行托盘图标
icon.run()
运行效果如下
打包
pyinstaller --onefile --noconsole test03.py
test03.py
是我写这个程序的文件名,你需要改成自己的
onefile
参数很容易理解,即单文件
--noconsle
参数也容易理解 no console
嘛!当然就是不显示cmd窗口了,不然好丑的说,而且关掉还会结束程序运行,不方便。