文章目录
- 一.前言
- 二.预览
- 1.主界面
- 2.动图演示
- 3.内存详细信息查看
- 4.自定义界面
- 三.源代码
- 1.tool_god_GUI.py
- 2.tool_god_ui.py
- 3.engine.py
- 4.CWidgets.py
- 四.总结
- 五.参考
一.前言
本次使用PyQt5进行开发一款网速内存查看小工具,类似于一个低配的“电脑管家加速小火箭”,支持实时内存、网速查看、详细内存占用情况查看。
二.预览
本次界面极其简单,实现功能较为单一
1.主界面
2.动图演示
3.内存详细信息查看
双左侧内存占用比,展示详细内存占用情况
4.自定义界面
可以自定义透明度以及背景颜色
三.源代码
1.tool_god_GUI.py
文件主逻辑调用
import sys
import webbrowserfrom PyQt5.QtCore import QTimer, Qt, QLockFile
from PyQt5.QtGui import QCursor, QColor
from PyQt5.QtWidgets import QMainWindow, QApplication, QGraphicsDropShadowEffect, QMessageBox, QMenu, QAction, \QColorDialog, QActionGroup
from qtpy import QtGui, QtCorefrom CWidgets import subThread
from tool_god_ui import Ui_MainWindow as mainWindow
from engine import speedEngine, Tool"""
https://blog.csdn.net/weixin_44446598/article/details/115031335
https://www.yingsoo.com/news/devops/38816.html
"""class toolGod(QMainWindow, mainWindow):__author_blog = "https://blog.csdn.net/a1397852386"def __init__(self, parent=None):super(toolGod, self).__init__()self.setupUi(self)self.engine = speedEngine()self.tool = Tool()self.ui_init()self.menu_init()self.slot_init()self.timer_init()def ui_init(self):self.setFixedHeight(40)self.setWindowFlags(Qt.WindowStaysOnTopHint | Qt.FramelessWindowHint | Qt.Tool)self.setAttribute(Qt.WA_TranslucentBackground) # 窗口透明def timer_init(self):self.memory_timer = QTimer(self)self.net_timer = QTimer(self)self.memory_timer.setInterval(1000)self.net_timer.setInterval(1000)self.memory_timer.timeout.connect(self.show_memory_percent)self.net_timer.timeout.connect(self.show_net_speed)self.memory_timer.start()self.net_timer.start()def menu_init(self):self.base_menu = QMenu(self)self.action_change_transparency = QMenu(self)self.action_change_transparency.setTitle("调整透明度")self.action_change_bg_color = QAction(self.base_menu)self.action_about_author = QAction(self.base_menu)self.action_quit = QAction(self.base_menu)self.action_about_author.setText("关于作者")self.action_quit.setText("退出")self.action_change_bg_color.setText("调整背景颜色")self.base_menu.addMenu(self.action_change_transparency)self.base_menu.addAction(self.action_change_bg_color)self.base_menu.addAction(self.action_about_author)self.base_menu.addAction(self.action_quit)self.action_trans5 = QAction(self.action_change_transparency)self.action_trans25 = QAction(self.action_change_transparency)self.action_trans50 = QAction(self.action_change_transparency)self.action_trans75 = QAction(self.action_change_transparency)self.action_trans100 = QAction(self.action_change_transparency)self.action_trans5.setText("5%")self.action_trans25.setText("25%")self.action_trans50.setText("50%")self.action_trans75.setText("75%")self.action_trans100.setText("100%")self.action_trans5.setCheckable(True)self.action_trans25.setCheckable(True)self.action_trans50.setCheckable(True)self.action_trans75.setCheckable(True)self.action_trans100.setCheckable(True)self.action_trans100.setChecked(True)group = QActionGroup(self)group.addAction(self.action_trans5)group.addAction(self.action_trans25)group.addAction(self.action_trans50)group.addAction(self.action_trans75)group.addAction(self.action_trans100)group.setExclusive(True)self.action_change_transparency.addActions([self.action_trans5, self.action_trans25, self.action_trans50, self.action_trans75, self.action_trans100])self.action_trans5.triggered.connect(lambda: self.change_bg_opacity(0.05))self.action_trans25.triggered.connect(lambda: self.change_bg_opacity(0.25))self.action_trans50.triggered.connect(lambda: self.change_bg_opacity(0.5))self.action_trans75.triggered.connect(lambda: self.change_bg_opacity(0.75))self.action_trans100.triggered.connect(lambda: self.change_bg_opacity(1))self.action_change_bg_color.triggered.connect(self.change_bg_color)self.action_about_author.triggered.connect(self.show_about_author)self.action_quit.triggered.connect(self.close)def slot_init(self):self.frame_3.customContextMenuRequested.connect(lambda: self.base_menu.exec_(QCursor.pos()))self.frame.mouse_double_signal.connect(self.show_memory_detail)def change_bg_opacity(self, opacity):"""改变窗口透明度:param opacity::return:"""self.setWindowOpacity(opacity)def change_bg_color(self):"""改变背景颜色:return:"""color = QColorDialog.getColor(QColor("white"), self, "请选择一种颜色")rgb_color_str = color.toRgb()rgb_str = "rgb(%s,%s,%s)" % (rgb_color_str.red(), rgb_color_str.green(),rgb_color_str.blue())self.frame_3.setStyleSheet("""#frame_3{background-color:%s;border:1px solid %s;border-radius:15px;}""" % (rgb_str, rgb_str))def show_memory_detail(self):"""展示详细内存信息:return:"""mem_total, mem_used, mem_free, mem_percent = self.tool.memory_format(self.engine.get_memory_detail())msg = """总内存:{}\n已使用:{}\n空闲:{}\n占用:{}""".format(mem_total, mem_used, mem_free, mem_percent)QMessageBox.information(self, "内存详细信息", msg)def show_about_author(self):"""关于作者:return:"""ret = QMessageBox.question(self, "关于作者", '你好我是懷淰メ\n是否要访问我的播客主页?', QMessageBox.Yes | QMessageBox.No,QMessageBox.Yes)if ret == QMessageBox.Yes:webbrowser.open(self.__author_blog)def show_memory_percent(self):"""内存占用百分比:return:"""memory_percent = self.engine.get_memory_percent()self.label_mem_precent.setText("{}%".format(memory_percent))def show_net_speed(self):"""展示当前网速:return:"""net_download_speed, net_upload_speed = self.engine.get_net_speed()self.label_net_upload.setText(self.tool.speed_format(net_upload_speed))self.label_net_download.setText(self.tool.speed_format(net_download_speed))def closeEvent(self, a0: QtGui.QCloseEvent):ret = QMessageBox.question(self, "退出", '确认要退出?', QMessageBox.Yes | QMessageBox.No,QMessageBox.Yes)if ret == QMessageBox.Yes:a0.accept()sys.exit(-1)else:a0.ignore()# 无边框的拖动def mouseMoveEvent(self, e: QtGui.QMouseEvent): # 重写移动事件try:self._endPos = e.pos() - self._startPosself.move(self.pos() + self._endPos)except (AttributeError, TypeError):passdef mousePressEvent(self, e: QtGui.QMouseEvent):if e.button() == QtCore.Qt.LeftButton:self._isTracking = Trueself._startPos = QtCore.QPoint(e.x(), e.y())def mouseReleaseEvent(self, e: QtGui.QMouseEvent):if e.button() == QtCore.Qt.LeftButton:self._isTracking = Falseself._startPos = Noneself._endPos = Noneif __name__ == '__main__':app = QApplication(sys.argv)# ui = toolGod()# ui.show()# sys.exit(app.exec_())lockFile = QLockFile("./lock.lock")if lockFile.tryLock(timeout=2000):ui = toolGod()ui.show()sys.exit(app.exec_())else:msg_box = QMessageBox()msg_box.setWindowTitle("警告")msg_box.setText("软件已在运行,请勿重复开启!")msg_box.setIcon(QMessageBox.Warning)msg_box.addButton("确定", QMessageBox.YesRole)msg_box.exec()sys.exit(-1)
2.tool_god_ui.py
由designer转化而来
# -*- coding: utf-8 -*-# Form implementation generated from reading ui file 'tool_god_ui.ui'
#
# Created by: PyQt5 UI code generator 5.15.4
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.from PyQt5 import QtCore, QtGui, QtWidgetsclass Ui_MainWindow(object):def setupUi(self, MainWindow):MainWindow.setObjectName("MainWindow")MainWindow.resize(143, 45)MainWindow.setStyleSheet("#label_4{color:rgb(0, 85, 255);font-weight:600;}\n"
"#label_5{color;green;font-weight:600;}\n"
"*{font-family:\"微软雅黑\"}\n"
"#frame_3{background-color:#00ffff;border:1px solid #00ffff ;border-radius:15px;}\n"
"#line{color:gray;}\n"
"\n"
"")self.centralwidget = QtWidgets.QWidget(MainWindow)self.centralwidget.setObjectName("centralwidget")self.verticalLayout_2 = QtWidgets.QVBoxLayout(self.centralwidget)self.verticalLayout_2.setContentsMargins(0, 0, 0, 0)self.verticalLayout_2.setSpacing(0)self.verticalLayout_2.setObjectName("verticalLayout_2")self.frame_3 = QtWidgets.QFrame(self.centralwidget)self.frame_3.setContextMenuPolicy(QtCore.Qt.CustomContextMenu)self.frame_3.setFrameShape(QtWidgets.QFrame.StyledPanel)self.frame_3.setFrameShadow(QtWidgets.QFrame.Raised)self.frame_3.setObjectName("frame_3")self.horizontalLayout = QtWidgets.QHBoxLayout(self.frame_3)self.horizontalLayout.setContentsMargins(0, 0, 0, 0)self.horizontalLayout.setSpacing(0)self.horizontalLayout.setObjectName("horizontalLayout")self.frame = myFrame(self.frame_3)self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)self.frame.setFrameShadow(QtWidgets.QFrame.Raised)self.frame.setObjectName("frame")self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.frame)self.horizontalLayout_2.setContentsMargins(10, 0, 10, 0)self.horizontalLayout_2.setSpacing(0)self.horizontalLayout_2.setObjectName("horizontalLayout_2")self.label_mem_precent = QtWidgets.QLabel(self.frame)self.label_mem_precent.setObjectName("label_mem_precent")self.horizontalLayout_2.addWidget(self.label_mem_precent)self.horizontalLayout.addWidget(self.frame)self.frame_2 = QtWidgets.QFrame(self.frame_3)self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)self.frame_2.setObjectName("frame_2")self.verticalLayout = QtWidgets.QVBoxLayout(self.frame_2)self.verticalLayout.setContentsMargins(0, 0, 10, 0)self.verticalLayout.setSpacing(0)self.verticalLayout.setObjectName("verticalLayout")self.horizontalLayout_4 = QtWidgets.QHBoxLayout()self.horizontalLayout_4.setObjectName("horizontalLayout_4")self.label_4 = QtWidgets.QLabel(self.frame_2)self.label_4.setObjectName("label_4")self.horizontalLayout_4.addWidget(self.label_4, 0, QtCore.Qt.AlignLeft)self.label_net_upload = QtWidgets.QLabel(self.frame_2)self.label_net_upload.setObjectName("label_net_upload")self.horizontalLayout_4.addWidget(self.label_net_upload)self.verticalLayout.addLayout(self.horizontalLayout_4)self.line = QtWidgets.QFrame(self.frame_2)sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Fixed)sizePolicy.setHorizontalStretch(0)sizePolicy.setVerticalStretch(0)sizePolicy.setHeightForWidth(self.line.sizePolicy().hasHeightForWidth())self.line.setSizePolicy(sizePolicy)self.line.setFrameShape(QtWidgets.QFrame.HLine)self.line.setFrameShadow(QtWidgets.QFrame.Sunken)self.line.setObjectName("line")self.verticalLayout.addWidget(self.line)self.horizontalLayout_3 = QtWidgets.QHBoxLayout()self.horizontalLayout_3.setObjectName("horizontalLayout_3")self.label_5 = QtWidgets.QLabel(self.frame_2)self.label_5.setObjectName("label_5")self.horizontalLayout_3.addWidget(self.label_5, 0, QtCore.Qt.AlignLeft)self.label_net_download = QtWidgets.QLabel(self.frame_2)self.label_net_download.setObjectName("label_net_download")self.horizontalLayout_3.addWidget(self.label_net_download)self.verticalLayout.addLayout(self.horizontalLayout_3)self.horizontalLayout.addWidget(self.frame_2)self.horizontalLayout.setStretch(0, 1)self.horizontalLayout.setStretch(1, 3)self.verticalLayout_2.addWidget(self.frame_3)MainWindow.setCentralWidget(self.centralwidget)self.retranslateUi(MainWindow)QtCore.QMetaObject.connectSlotsByName(MainWindow)def retranslateUi(self, MainWindow):_translate = QtCore.QCoreApplication.translateMainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))self.label_mem_precent.setText(_translate("MainWindow", "0.0%"))self.label_4.setText(_translate("MainWindow", "↑"))self.label_net_upload.setText(_translate("MainWindow", "0k/s"))self.label_5.setText(_translate("MainWindow", "↓"))self.label_net_download.setText(_translate("MainWindow", "0k/s"))
from CWidgets import myFrame
3.engine.py
主要引擎、工具类,获取网速、内存、单位格式转化
import psutil
import tracebackclass speedEngine(object):last_total_bytes_sent = psutil.net_io_counters().bytes_sentlast_total_bytes_recv = psutil.net_io_counters().bytes_recvdef get_net_speed(self):"""获取网络上传下载速度:return:"""try:total_bytes_sent = psutil.net_io_counters().bytes_senttotal_bytes_recv = psutil.net_io_counters().bytes_recvdiff_bytes_sent = (total_bytes_sent - self.last_total_bytes_sent) / 1024diff_bytes_recv = (total_bytes_recv - self.last_total_bytes_recv) / 1024net_download_speed = diff_bytes_recv / 1net_upload_speed = diff_bytes_sent / 1self.last_total_bytes_sent = total_bytes_sentself.last_total_bytes_recv = total_bytes_recvreturn net_download_speed, net_upload_speedexcept:traceback.print_exc()return "", ""def get_memory_percent(self):"""获取内存占用:return:"""try:memory_percent = psutil.virtual_memory().percentreturn memory_percentexcept:traceback.print_exc()return 0.0def get_memory_detail(self):"""获取内存占用详细情况:return:"""try:mem = psutil.virtual_memory()return memexcept:traceback.print_exc()return ""class Tool():def speed_format(self, speed: float):"""格式化网速:param speed::return:"""if int(speed) > 1024:return "%.2f M/s" % (speed / 1024)else:return "%.2f k/s" % (speed)def memory_format(self, mem):"""格式化内存:param mem::return:"""mem_total = mem.total / 1024 / 1024 / 1024 # 获取内存的总数mem_used = mem.used / 1024 / 1024 / 1024 # 获取已使用的内存mem_free = mem.free / 1024 / 1024 / 1024 # 获取空闲内存大小mem_percent = mem.percent # 获取空闲内存占用比format_str = "{:.2f}GB"return format_str.format(mem_total), format_str.format(mem_used), format_str.format(mem_free), "{:.2f}%".format(mem_percent)if __name__ == '__main__':tool = speedEngine()print(tool.get_memory_detail())
4.CWidgets.py
自定义Frame,支持双击响应
import sysfrom PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QMouseEvent
from PyQt5.QtWidgets import QWidget, QApplication, QFramefrom engine import speedEngine
from bak.memory_detail_ui import Ui_Form as memory_detailclass myFrame(QFrame):mouse_double_signal = pyqtSignal()def __init__(self, parent=None):super(myFrame, self).__init__()self.setParent(parent)def mouseDoubleClickEvent(self, a0: QMouseEvent):print("double click")self.mouse_double_signal.emit()super(myFrame, self).mouseDoubleClickEvent(a0)class subThread(QThread):memory_percent_finished = pyqtSignal(str)net_speed_finished = pyqtSignal(str, str)def __init__(self, task, *arg, **args):super(subThread, self).__init__()self.engine = speedEngine()def get_mem_percent(self):mem_percent = self.engine.get_memory_percent()self.memory_percent_finished.emit(mem_percent)def get_net_speed(self):net_download_speed, net_upload_speed = self.engine.get_net_speed()self.net_speed_finished.emit(net_download_speed, net_upload_speed)class memoryDetail(QWidget, memory_detail):def __init__(self):super(memoryDetail, self).__init__()self.setupUi(self)if __name__ == '__main__':app = QApplication(sys.argv)ui = memoryDetail()ui.show()sys.exit(app.exec_())
四.总结
本次使用PyQt5模仿电脑管家内存、网速查看工具,实现了网速、内存的实时展示、详细内存查看、自定义界面透明度、背景颜色。软件打包好放在了蓝奏云。软件无恶意代码,但有可能会被误报,添加信任即可。如果觉得小工具还可以,能留下您的赞么?
五.参考
- Python实现桌面悬浮窗(显示网速,内存,CPU)
- Python PyQt5实战项目之网速监控器的实现