python3GUI--网速内存小工具By:PyQt5(附源码)

news/2024/11/2 6:37:29/

文章目录

  • 一.前言
  • 二.预览
    • 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模仿电脑管家内存、网速查看工具,实现了网速、内存的实时展示、详细内存查看、自定义界面透明度、背景颜色。软件打包好放在了蓝奏云。软件无恶意代码,但有可能会被误报,添加信任即可。如果觉得小工具还可以,能留下您的赞么?
在这里插入图片描述

五.参考

  1. Python实现桌面悬浮窗(显示网速,内存,CPU)
  2. Python PyQt5实战项目之网速监控器的实现

http://www.ppmy.cn/news/686238.html

相关文章

Visdom使用

Visdom Visdom是一个面向科学研究的可视化工具,可以帮助你可视化和理解数据。它是 Facebook Research 开发的一个基于 Python 的可视化库,可以在Web浏览器中实时显示和更新图表、图像、文本等各种数据。 1 安装Visdom 可以使用以下命令安装Visdom&…

手机银行APP开发新门户

随着3G、4G技术的发展和智能手机的普及,手机银行APP开发的服务范围、业务功能和发展定位都发生了很大的变化,它不再只是局限于提供传统意义上的银行业务。 监测数据显示,手机银行作为一款特殊的APP,尽管我国四大行和股份制银行的用…

惊!又一家知名企业被查!

10月21日上午,港股上市公司“51信用卡”位于杭州西溪谷的办公地点突然遭警方调查。 01.警方突袭 杭州警方突击调查了51信用卡公司,据网上的视频信息看出,大约出动了上百名警力,带走了CEO兼公司法定代表人孙海涛,同时…

又一知名公司雷炸,如何避免面向监狱编程

10月21日上午,港股上市公司“51信用卡”位于杭州西溪谷的办公地点突然遭警方调查。 01.警方突袭 杭州警方突击调查了51信用卡公司,据网上的视频信息看出,大约出动了上百名警力,带走了CEO兼公司法定代表人孙海涛,同时还…

个人隐私的泄露在日常工作、生活、学习中,每个人都要学会保护自己的个人隐私

电脑一定不要裸奔,勤打补丁,用腾讯管家、百度卫士、360安全卫士都可以,增加安全防护。 不要随便在网上留个人真实信息,如QQ号、姓名、家庭住址、身份证号等。 重要网站、APP 的密码一定不要太简单,比如生日、名字拼音…

互联网免费时代即将终结 付费时代到来

从前,它是一只戴围脖的企鹅管家,一开始您靠它泡妞扯淡,后来它帮您发短信、玩游戏、传文件、看视频、开邮箱、买东西…… 从前,他是一位智商250的110警察,先是主动为您挡流氓,后来义务给您修系统、杀病毒、管…

免费时代即将终结 互联网付费时代到来

从前,它是一只戴围脖的企鹅管家,一开始您靠它泡妞扯淡,后来它帮您发短信、玩游戏、传文件、看视频、开邮箱、买东西…… 从前,他是一位智商250的110警察,先是主动为您挡流氓,后来义务给您修系统、杀病毒、管…

第七周学习笔记

三、网络安全与管理 (一)网络安全威胁 网络安全: 目的就是要让网络入侵者进不了网络系统,即使强行攻入网络,也拿不走信息,改不了数据,看不懂信息,事发后能审查追踪到破坏者&#…