说明:
所有源代码并非原创,转自:https://github.com/mingo-meo/floating-monitor
monitor_Qthread.py
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5.QtCore import Qt
from PyQt5 import QtCore
from PyQt5 import QtWidgets
import psutil
import sys
import time
class WorkThread(QThread):
# 实例化一个信号对象,类变量,需要定义在函数体外
trigger = pyqtSignal()
def __init__(self):
super().__init__()
self.receive_pre = -1
self.sent_pre = -1
self.upload_bytes = 0
self.upload_string = '↑' + '0B/S'
self.download_bytes = 0
self.download_string = '↓' + '0B/S'
self.one_line = ''.join(['*' for i in range(40)])
self.cpu_percent = 0
self.cpu_percent_string = '0%'
self.mem_percent = 0
self.mem_percent_string = '0%'
self.cpu_lines = ''
self.mem_lines = ''
@staticmethod
def standard_net_speed(net_bytes: int):
# xx.xB/S or xxxB/S
if net_bytes < 1000:
if net_bytes < 100:
return " %sB/S" % str(net_bytes)
else:
return "%sB/S" % str(net_bytes)
elif net_bytes >> 10 < 1000:
if net_bytes // 1024 < 100:
return "%.1fKB/S" % (net_bytes / 1024)
else:
return "%sKB/S" % (net_bytes // 1024)
elif net_bytes >> 20 < 1000:
if net_bytes // 1024**2 < 100:
return "%.1fMB/S" % (net_bytes / 1024**2)
else:
return "%sMB/S" % (net_bytes // 1024**2)
elif net_bytes >> 30 < 1024:
if net_bytes // 1024 ** 3 < 100:
return "%.1fGB/S" % (net_bytes / 1024 ** 3)
else:
return "%sGB/S" % (net_bytes // 1024 ** 3)
else:
return "xx.xB/S"
def get_computer_info(self):
self.get_net_speed()
self.get_cpu_mem()
def get_net_speed(self):
# 获取网速,当sent_pre或receive_pre为-1时,初始化窗口
if self.sent_pre == -1 or self.receive_pre == -1:
self.upload_bytes = 0
self.download_bytes = 0
try:
self.sent_pre = psutil.net_io_counters().bytes_sent
self.receive_pre = psutil.net_io_counters().bytes_recv
except RuntimeError:
# 如果获取失败,重新获取
self.sent_pre = -1
self.receive_pre = -1
else:
try:
# 长时间休眠后,会出现RuntimeError
self.upload_bytes = psutil.net_io_counters().bytes_sent - self.sent_pre
self.download_bytes = psutil.net_io_counters().bytes_recv - self.receive_pre
except RuntimeError:
self.sent_pre = -1
self.receive_pre = -1
self.upload_string = '↑' + '0B/S'
self.download_string = '↓' + '0B/S'
else:
self.sent_pre += self.upload_bytes
self.receive_pre += self.download_bytes
self.upload_string = '↑' + WorkThread.standard_net_speed(self.upload_bytes)
self.download_string = '↓' + WorkThread.standard_net_speed(self.download_bytes)
def get_cpu_mem(self):
self.cpu_percent = (psutil.cpu_percent(interval=0.0, percpu=False))
self.mem_percent = psutil.virtual_memory().percent
if self.cpu_percent >= 100:
self.cpu_percent = 99
if self.mem_percent >= 100:
self.mem_percent = 99
self.cpu_lines = ''.join([self.one_line + '\n' for i in range(int(self.cpu_percent) // 10)])
self.mem_lines = ''.join([self.one_line + '\n' for i in range(int(self.mem_percent) // 10)])
self.cpu_percent_string = "%d" % self.cpu_percent + '%'
self.mem_percent_string = "%d" % self.mem_percent + '%'
def run(self):
# 重写QThread 的run 函数
while True:
self.get_computer_info()
# 信号发出通知面板更新
self.trigger.emit()
time.sleep(1)
class Monitor(QWidget):
def __init__(self):
super().__init__()
self._startPos = None
self._wmGap = None
self.hidden = False
dsk = QApplication.primaryScreen()
self.screen_width = dsk.geometry().width()
self.screen_height = dsk.geometry().height()
self.window_width = 140
self.window_height = 50
self.label_size = 'font: 13px'
self.cpu_gui_x = 75
# Inform threading.Timer
self.ui_alive = True
# 设置窗口无边框; 设置窗口置顶;
self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint | Qt.Tool)
# 设置窗口背景透明
# self.setAttribute(Qt.WA_TranslucentBackground)
# 设置透明度(0~1)
self.setWindowOpacity(0.9)
# 设置鼠标为手状
self.setCursor(Qt.PointingHandCursor)
# 实例化,将信号连接
self.work_threading = WorkThread()
self.work_threading.trigger.connect(self.update_ui_label)
def enterEvent(self, event):
self.hide_or_show('show', event)
def leaveEvent(self, event):
self.hide_or_show('hide', event)
def hide_or_show(self, mode, event):
# 获取窗口左上角x,y
pos = self.frameGeometry().topLeft()
if mode == 'show' and self.hidden:
# 窗口左上角x + 窗口宽度 大于屏幕宽度,从右侧滑出
if pos.x() + self.window_width >= self.screen_width:
# 需要留10在里边,否则边界跳动
self.startAnimation(self.screen_width - self.window_width, pos.y())
event.accept()
self.hidden = False
# 窗口左上角x 小于0, 从左侧滑出
elif pos.x() = self.screen_width:
# 需要留10在里边,否则边界跳动
self.startAnimation(self.screen_width - self.window_width, pos.y())
event.accept()
self.hidden = False
# 窗口左上角x 小于0, 从左侧滑出
elif pos.x() > 10 < 1000:
if net_bytes // 1024 < 100:
return "%.1fKB/S" % (net_bytes / 1024)
else:
return "%sKB/S" % (net_bytes // 1024)
elif net_bytes >> 20 < 1000:
if net_bytes // 1024 ** 2 < 100:
return "%.1fMB/S" % (net_bytes / 1024 ** 2)
else:
return "%sMB/S" % (net_bytes // 1024 ** 2)
elif net_bytes >> 30 < 1024:
if net_bytes // 1024 ** 3 < 100:
return "%.1fGB/S" % (net_bytes / 1024 ** 3)
else:
return "%sGB/S" % (net_bytes // 1024 ** 3)
else:
return "xx.xB/S"
def get_computer_info(self):
self.get_net_speed()
self.get_cpu_mem()
# 通知面板更新
self.trigger.emit()
if self.ui_alive:
# 重新设置定时器
self.timer = threading.Timer(1, self.get_computer_info)
self.timer.start()
def get_net_speed(self):
# 获取网速,当sent_pre或receive_pre为-1时,初始化窗口
if self.sent_pre == -1 or self.receive_pre == -1:
self.upload_bytes = 0
self.download_bytes = 0
try:
self.sent_pre = psutil.net_io_counters().bytes_sent
self.receive_pre = psutil.net_io_counters().bytes_recv
except RuntimeError:
# 如果获取失败,重新获取
self.sent_pre = -1
self.receive_pre = -1
else:
try:
self.upload_bytes = psutil.net_io_counters().bytes_sent - self.sent_pre
self.download_bytes = psutil.net_io_counters().bytes_recv - self.receive_pre
except RuntimeError:
self.sent_pre = -1
self.receive_pre = -1
self.upload_string = '↑' + '0B/S'
self.download_string = '↓' + '0B/S'
else:
self.sent_pre += self.upload_bytes
self.receive_pre += self.download_bytes
self.upload_string = '↑' + Monitor.standard_net_speed(self.upload_bytes)
self.download_string = '↓' + Monitor.standard_net_speed(self.download_bytes)
def get_cpu_mem(self):
self.cpu_percent = (psutil.cpu_percent(interval=0.0, percpu=False))
self.mem_percent = psutil.virtual_memory().percent
if self.cpu_percent >= 100:
self.cpu_percent = 99
if self.mem_percent >= 100:
self.mem_percent = 99
self.cpu_lines = ''.join([self.one_line + '\n' for i in range(int(self.cpu_percent) // 10)])
self.mem_lines = ''.join([self.one_line + '\n' for i in range(int(self.mem_percent) // 10)])
self.cpu_percent_string = "%d" % self.cpu_percent + '%'
self.mem_percent_string = "%d" % self.mem_percent + '%'
def update_ui_label(self):
self.upspeed.setText(self.upload_string)
self.downspeed.setText(self.download_string)
self.cpu_num.setText("%d" % self.cpu_percent + '%')
self.mem_num.setText("%d" % self.mem_percent + '%')
self.cpu_gui.setText(self.cpu_lines)
self.mem_gui.setText(self.mem_lines)
if __name__ == '__main__':
# 设置屏幕自适应
QtCore.QCoreApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
app = QApplication([])
# 获取主显示器分辨率
screen_width = app.primaryScreen().geometry().width()
screen_height = app.primaryScreen().geometry().height()
stats = Monitor()
stats.setupUi()
stats.retranslateUi()
# 设置最初出现的位置
window_width = stats.geometry().width()
window_height = stats.geometry().height()
stats.setGeometry(screen_width - window_width - 10, screen_height//2 - 150, window_width, window_height)
stats.show()
sys.exit(app.exec_())
monitor_ui.py
# -*- coding: utf-8 -*-
################################################################################
## Form generated from reading UI file 'monitor.ui'
##
## Created by: Qt User Interface Compiler version 5.15.2
##
## WARNING! All changes made in this file will be lost when recompiling UI file!
################################################################################
from PySide2.QtCore import QPropertyAnimation, QRect, Qt, QCoreApplication, QMetaObject
from PySide2.QtGui import QMouseEvent, QFont
from PySide2.QtWidgets import QWidget, QApplication, QMenu, QLabel
from PySide2 import QtWidgets
class Ui_Form(QWidget, object):
def __init__(self):
super().__init__()
self._startPos = None
self._wmGap = None
self.hidden = False
dsk = QApplication.primaryScreen()
self.screen_width = dsk.geometry().width()
self.screen_height = dsk.geometry().height()
self.window_width = 140
self.window_height = 50
self.label_size = 'font: 13px'
self.cpu_gui_x = 75
# Inform threading.Timer
self.ui_alive = True
def enterEvent(self, event):
self.hide_or_show('show', event)
def leaveEvent(self, event):
self.hide_or_show('hide', event)
def hide_or_show(self, mode, event):
# 获取窗口左上角x,y
pos = self.frameGeometry().topLeft()
if mode == 'show' and self.hidden:
# 窗口左上角x + 窗口宽度 大于屏幕宽度,从右侧滑出
if pos.x() + self.window_width >= self.screen_width:
# 需要留10在里边,否则边界跳动
self.startAnimation(self.screen_width - self.window_width, pos.y())
event.accept()
self.hidden = False
# 窗口左上角x 小于0, 从左侧滑出
elif pos.x() = 100:
cpu_percent = 99
if mem_percent >= 100:
mem_percent = 99
cpu_lines = ''.join([self.one_line + '\n' for i in range(int(cpu_percent)//10 + 1)])
mem_lines = ''.join([self.one_line + '\n' for i in range(int(mem_percent) // 10 + 1)])
self.cpu_num.setText("%d" % cpu_percent + '%')
self.mem_num.setText("%d" % mem_percent + '%')
self.cpu_gui.setText(cpu_lines)
self.mem_gui.setText(mem_lines)
@staticmethod
def standard_net_speed(net_bytes: int):
# xx.xB/S or xxxB/S
if net_bytes < 1000:
if net_bytes < 100:
return " %sB/S" % str(net_bytes)
else:
return "%sB/S" % str(net_bytes)
elif net_bytes >> 10 < 1000:
if net_bytes // 1024 < 100:
return "%.1fKB/S" % (net_bytes / 1024)
else:
return "%sKB/S" % (net_bytes // 1024)
elif net_bytes >> 20 < 1000:
if net_bytes // 1024**2 < 100:
return "%.1fMB/S" % (net_bytes / 1024**2)
else:
return "%sMB/S" % (net_bytes // 1024**2)
elif net_bytes >> 30 < 1024:
if net_bytes // 1024 ** 3 < 100:
return "%.1fGB/S" % (net_bytes / 1024 ** 3)
else:
return "%sGB/S" % (net_bytes // 1024 ** 3)
else:
return "xx.xB/S"
if __name__ == '__main__':
# 设置屏幕自适应
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
app = QApplication([])
# 获取主显示器分辨率
screen_width = app.primaryScreen().geometry().width()
screen_height = app.primaryScreen().geometry().height()
stats = Stats()
# 设置最初出现的位置
window_width = stats.geometry().width()
window_height = stats.geometry().height()
stats.setGeometry(screen_width - window_width - 10, screen_height//2 - 150, window_width, window_height)
stats.show()
sys.exit(app.exec_())
monitor.ui
Form
0
0
214
141
background-color: rgb(0, 0, 0);
80
39
22
31
Agency FB
1
75
true
false
Qt::LeftToRight
color: rgb(85, 170, 255);
border: 1px solid;
border-color: rgb(85, 170, 255);
*************************************
*******************************************
*************************************
***********************************
*************************
***********************************
***************************************
*******************************************
********************************
*********************************
Qt::AutoText
false
Qt::AlignBottom|Qt::AlignHCenter
false
0
-3
80
21
16
16
color: rgb(85, 170, 255);
0%
Qt::AlignCenter
120
40
22
31
Agency FB
1
75
true
false
Qt::LeftToRight
color: rgb(170, 255, 255);
border: 1px solid;
border-color: rgb(170, 255, 255);
*************************************
*******************************************
*************************************
***********************************
*************************
***********************************
***************************************
*******************************************
********************************
*********************************
Qt::AutoText
false
Qt::AlignBottom|Qt::AlignHCenter
false
0
-3
120
22
18
16
color: rgb(170, 255, 255);
99%
Qt::AlignCenter
10
60
68
12
color: rgb(85, 255, 0);
100.5KB/S
10
30
54
16
color: rgb(255, 170, 0);
100.5KB/S
layoutWidget
cpu_num
cpu_gui
mem_num
mem_gui
downspeed
pyinstaller_build.bat
REM Use pyinstaller.exe under python3.9
pyinstaller -F -w -i monitor.ico monitor.py
ui2py.bat
pyside2-uic.exe monitor.ui > monitor_ui.py
|