2025年1月31日 星期五 甲辰(龙)年 冬月廿九 设为首页 加入收藏
rss
您当前的位置:首页 > 计算机 > 编程开发 > Python

python --windows系统托盘pystray/自实现

时间:08-13来源:作者:点击数:20
城东书院 www.cdsy.xyz

python --windos系统托盘pystray/自实现

pystray安装

  • pip install pystray

示例

  • import os
  • import signal
  • import subprocess
  • import tempfile
  • def open_chromium():
  • '''系统托盘重启界面'''
  • temp_profile_dir = os.path.join(tempfile.gettempdir(), "flaskwebgui")
  • launch_options = [f"--window-size=1300,800"]
  • options = [
  • get_default_chrome_path(),
  • f"--user-data-dir={temp_profile_dir}",
  • "--new-window",
  • "--no-first-run",
  • ] + launch_options + [f'--app=http://127.0.0.1:8001']
  • subprocess.Popen(options, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
  • def _kill():
  • ThreadPid.update(query={'arrange_id': 1}, data={'status': 0})
  • logger.error('调用用户退出')
  • handle = os.getpid()
  • logger.error(f'pid={handle}')
  • os.kill(handle, signal.SIGABRT)
  • image = Image.open('logo.ico')
  • icon = pystray.Icon('Neural', image, menu=pystray.Menu(
  • pystray.MenuItem('打开主界面', open_chromium),
  • pystray.MenuItem('退出', _kill)))
  • icon.run_detached() #【注】 后台运行(必须有父进程)
  • # ThreadPid.update(query={'arrange_id': 1}, data={'status': 1})
  • # icon.run() #【注】 阻塞运行;

绑定鼠标左键被单击事件

  • from PIL import Image
  • import pystray
  • image = Image.open('logo.ico')
  • icon = pystray.Icon('Neural', image, title='11', menu=pystray.Menu(
  • pystray.MenuItem('打开主界面', lambda x: print(1), default=True), # 鼠标被单击事件
  • pystray.Menu.SEPARATOR,
  • pystray.MenuItem('退出', lambda x: print(2)),
  • pystray.Menu.SEPARATOR,
  • ))
  • icon.run() # 【注】 此方式为阻塞

自实现

  • import win32con
  • import win32gui
  • import time
  • import abc
  • from threading import Thread
  • class Pystray(object):
  • '''windows添加系统托盘'''
  • def __init__(self, ico_path: str, ico_class_name: str, window_name: str='mywindowclass'):
  • '''
  • @params ico_path --> 系统托盘图标路径;
  • @params ico_class_name --> 图标名;
  • @params window_name --> 窗口类(非必要);
  • '''
  • self._ico_path: str = ico_path
  • self._ico_class_name = ico_class_name
  • self.__window_name = window_name
  • self._menu = {} # {1024: ('菜单名', fun1), 1025: ('菜单名1', fun2)}
  • @property
  • def menu(self): return self._menu
  • @menu.setter
  • def menu(self, value: dict):
  • if isinstance(value, dict):
  • self._menu.update(value)
  • else:
  • raise TypeError('参数必须为字典;{1024: (菜单名, fun1), 1025: (菜单名1, fun2)}')
  • @abc.abstractmethod
  • def left_doubleclick(self):
  • '''鼠标左键双击事件'''
  • print("鼠标左键被双击了")
  • @abc.abstractmethod
  • def left_click(self):
  • '''鼠标左键单击事件'''
  • print("鼠标左键被单击了")
  • @abc.abstractmethod
  • def right_doubleclick(self):
  • '''鼠标右键双击事件'''
  • print("鼠标右键被双击了!")
  • def _create_window(self):
  • '''创建window对象'''
  • wc = win32gui.WNDCLASS()
  • self.hinst = wc.hInstance = win32gui.GetModuleHandle(None)
  • wc.lpszClassName = self.__window_name
  • wc.lpfnWndProc = self.wndProc
  • self.classAtom = win32gui.RegisterClass(wc)
  • def create_tray_icon(self):
  • '''创建图标'''
  • self._create_window()
  • self.hwnd = win32gui.CreateWindow(self.classAtom, self.__window_name, win32con.WS_OVERLAPPED | win32con.WS_SYSMENU, 0, 0,
  • win32con.CW_USEDEFAULT, win32con.CW_USEDEFAULT, 0, 0, self.hinst, None)
  • icon_flags = win32con.LR_LOADFROMFILE | win32con.LR_DEFAULTSIZE
  • hicon = win32gui.LoadImage(self.hinst, self._ico_path, win32con.IMAGE_ICON, 0, 0, icon_flags)
  • # 设置系统托盘图标的属性
  • flags = win32gui.NIF_ICON | win32gui.NIF_MESSAGE | win32gui.NIF_TIP
  • nid = (self.hwnd, 0, flags, win32con.WM_USER + 20, hicon, self._ico_class_name)
  • win32gui.Shell_NotifyIcon(win32gui.NIM_ADD, nid)
  • @abc.abstractmethod
  • def wndProc(self, hwnd, msg, wparam, lparam):
  • ''' 定义系统托盘图标的消息处理函数'''
  • if msg == win32con.WM_USER + 20: # 监听系统托盘图标的消息
  • if lparam == win32con.WM_LBUTTONDBLCLK: # 监听鼠标左键双击事件
  • self.left_doubleclick()
  • elif lparam == win32con.WM_RBUTTONDOWN: # 监听右键单击事件
  • # 显示右键菜单
  • menu = win32gui.CreatePopupMenu()
  • # for k, v in self._menu.items():
  • # ids, name = k, v[0]
  • # win32gui.AppendMenu(menu, win32con.MF_STRING, ids, name)
  • win32gui.AppendMenu(menu, win32con.MF_STRING, 1023, "菜单项1")
  • win32gui.AppendMenu(menu, win32con.MF_STRING, 1024, "菜单项2")
  • win32gui.AppendMenu(menu, win32con.MF_STRING, 1025, "退出")
  • pos = win32gui.GetCursorPos()
  • win32gui.SetForegroundWindow(hwnd)
  • win32gui.TrackPopupMenu(menu, win32con.TPM_LEFTALIGN, pos[0], pos[1], 0, hwnd, None)
  • win32gui.PostMessage(hwnd, win32con.WM_NULL, 0, 0)
  • elif lparam == win32con.WM_LBUTTONDOWN: # 监听鼠标左键单击事件
  • self.left_click()
  • elif lparam == win32con.WM_RBUTTONDBLCLK: # 监听右键双击事件
  • self.right_doubleclick()
  • elif msg == win32con.WM_COMMAND:
  • id = win32gui.LOWORD(wparam)
  • if id == 1023:
  • print("执行菜单项1的操作")
  • elif id == 1024:
  • print("执行菜单项2的操作")
  • elif id == 1025:
  • win32gui.DestroyWindow(hwnd)
  • return win32gui.DefWindowProc(hwnd, msg, wparam, lparam)
  • def run(self):
  • '''消息循环(正常启动)'''
  • self.create_tray_icon()
  • while True:
  • time.sleep(0.1)
  • win32gui.PumpWaitingMessages()
  • def run_detached(self):
  • '''非阻塞(须有父进程)'''
  • t = Thread(target=a.run)
  • t.daemon = True
  • t.start()
  • if __name__ == "__main__":
  • a = Pystray('logo.ico', 'edg')
  • # a.run()
  • a.run_detached()
城东书院 www.cdsy.xyz
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐