runcat-pyqt5-win:在windows任务栏养猫(2
2020-04-08 本文已影响0人
洗洗睡吧i
runcat-pyqt5-win V2
之前撸了一个 runcat-pyqt5-win
,可以在windows任务栏养猫,用奔跑的猫来显示当前系统资源的占用情况。
- github仓库: https://github.com/shenbo/runcat-pyqt5-win
- 原mac应用: RunCat
原来的功能比较简单,这次增加了右键菜单:
- 可切换图标类型: [cat, mario]
- 可切换监控类型: [cpu, memory, gpu(nVidia)]
- 增加了退出按钮
运行效果

Requirements
- psutil
- pyqt5
- nvidia-ml-py
完整代码
import os
import sys
import threading
import time
import psutil
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMenu, QAction
import pynvml
pynvml.nvmlInit()
handle = pynvml.nvmlDeviceGetHandleByIndex(0) # GPU id: 0
class TrayIcon(QSystemTrayIcon):
def __init__(self, parent=None):
super(TrayIcon, self).__init__(parent)
self.monitor = 'cpu'
self.cpu_usage = 0.2 # 初始化
self.mem_usage = 0.2 # 初始化
self.gpu_usage = 0.2 # 初始化
self.icon_type = 'runcat' # 设定默认图标,并加载
self.icon_list = self.loadIcon()
self.setIcon(self.icon_list[0])
self.setVisible(True)
self.setMenu() # 加载菜单
self.updateIcon() # 更新图标
# 加载图标
def loadIcon(self):
if self.icon_type == 'mario':
return [QIcon(f'icons/{self.icon_type}/{i}.png') for i in range(3)]
return [QIcon(f'icons/{self.icon_type}/{i}.png') for i in range(5)]
# 设置菜单
def setMenu(self):
self.menu = QMenu()
self.action_1 = QAction(QIcon(f'icons/cat.png'),
'Cat', self, triggered=lambda: self.changeIconType('runcat'))
self.action_2 = QAction(QIcon(f'icons/mario/0.png'),
'Mario', self, triggered=lambda: self.changeIconType('mario'))
self.action_c = QAction(QIcon(f'icons/cpu.png'),
'CPU', self, triggered=lambda: self.changeMonitor('cpu'))
self.action_m = QAction(QIcon(f'icons/mem.png'),
'Memory', self, triggered=lambda: self.changeMonitor('mem'))
self.action_g = QAction(QIcon(f'icons/gpu.png'),
'GPU', self, triggered=lambda: self.changeMonitor('gpu'))
self.action_q = QAction(QIcon(f'icons/quit.png'),
'Quit', self, triggered=self.quit)
self.menu.addAction(self.action_c)
self.menu.addAction(self.action_m)
self.menu.addAction(self.action_g)
self.menu.addSeparator()
self.menu.addAction(self.action_1)
self.menu.addAction(self.action_2)
self.menu.addSeparator()
self.menu.addAction(self.action_q)
self.setContextMenu(self.menu)
# 根据使用率更新图标,
# 创建两个 threading:一个获取使用率,一个更新图标
def updateIcon(self):
threading.Timer(0.1, self.thread_get_cpu_usage, []).start()
threading.Timer(0.1, self.thread_update_icon, []).start()
# get cpu usage
def thread_get_cpu_usage(self):
while True:
self.cpu_usage = psutil.cpu_percent(interval=1) / 100
self.mem_usage = psutil.virtual_memory().percent / 100
meminfo = pynvml.nvmlDeviceGetMemoryInfo(handle)
self.gpu_usage = meminfo.used / meminfo.total
# print(self.cpu_usage)
time.sleep(0.5)
# update icon
def thread_update_icon(self):
while True:
mon = self.cpu_usage
if self.monitor == 'mem':
mon = self.mem_usage
elif self.monitor == 'gpu':
mon = self.gpu_usage
t = 0.18 - mon * 0.15
# print(mon, t)
for i in self.icon_list:
self.setIcon(i)
tip = f'cpu: {self.cpu_usage:.2%} \nmem: {self.mem_usage:.2%} \ngpu: {self.gpu_usage:.2%}'
self.setToolTip(tip)
# print(i, self.cpu_usage)
time.sleep(t)
# Change icon type
def changeIconType(self, type):
print(type)
if type != self.icon_type:
self.icon_type = type
self.icon_list = self.loadIcon()
print(f'Load {self.icon_type}({len(self.icon_list)}) icons...')
# change monitor type
def changeMonitor(self, monitor_type):
print(monitor_type)
if monitor_type != self.monitor:
self.monitor = monitor_type
# 退出程序
def quit(self):
self.setVisible(False)
app.quit()
os._exit(-1) # 完全退出程序
if __name__ == "__main__":
app = QApplication(sys.argv)
tray = TrayIcon()
sys.exit(app.exec_())