Python打造轻量级系统监控悬浮窗:从零到一实现CPU、内存、网速实时可视化
1. 为什么需要系统监控悬浮窗作为一个经常需要关注电脑性能的开发者我发现自己总是在任务管理器和各种监控软件之间来回切换。这不仅浪费时间还容易打断工作流。于是我开始寻找一种更优雅的解决方案——一个始终显示在桌面上的轻量级监控悬浮窗。这种悬浮窗有几个明显的优势实时可见不用频繁切换窗口就能看到关键指标低干扰可以调整透明度不影响其他工作自定义性强可以只显示你关心的数据资源占用低相比完整版的任务管理器要轻量得多我试过市面上的一些现成工具但要么功能太多太臃肿要么缺少我想要的功能点。于是决定用Python自己开发一个正好也分享一下开发过程中的经验和踩过的坑。2. 开发环境准备2.1 基础工具安装首先确保你已经安装了Python建议3.7版本。我实测过3.9和3.10都能完美运行。然后通过pip安装必要的库pip install PyQt5 psutil pyinstaller这里解释下这几个库的作用PyQt5用来创建图形界面psutil获取系统信息CPU、内存、网络等pyinstaller最后打包成exe用注意如果你遇到安装问题可以尝试使用清华镜像源pip install -i https://pypi.tuna.tsinghua.edu.cn/simple PyQt5 psutil pyinstaller2.2 开发工具选择我推荐使用VS Code或PyCharm这类现代IDE它们对Qt开发有很好的支持。特别是VS Code的Python插件能提供很好的代码提示和调试体验。如果你打算长期做Qt开发也可以安装Qt Designer来可视化设计界面。不过我们这个项目比较简单直接代码写界面就够用了。3. 创建基础悬浮窗3.1 初始化无边框窗口我们先创建一个最基本的透明无边框窗口from PyQt5.QtWidgets import QApplication, QLabel, QWidget from PyQt5.QtCore import Qt import sys class MonitorWindow(QWidget): def __init__(self): super().__init__() self.initUI() def initUI(self): # 设置窗口无边框和置顶 self.setWindowFlags(Qt.FramelessWindowHint | Qt.WindowStaysOnTopHint) # 设置窗口透明 self.setAttribute(Qt.WA_TranslucentBackground) # 设置初始大小和位置 self.setGeometry(100, 100, 200, 100) # 添加一个标签显示文字 self.label QLabel(Hello Monitor, self) self.label.setStyleSheet(color: white; font-size: 16px;) self.label.move(10, 10) if __name__ __main__: app QApplication(sys.argv) win MonitorWindow() win.show() sys.exit(app.exec_())这段代码创建了一个最简单的悬浮窗目前还只能显示静态文字。几个关键点FramelessWindowHint去掉了窗口边框WindowStaysOnTopHint让窗口始终在最上层WA_TranslucentBackground实现透明背景3.2 实现窗口拖拽功能因为去掉了标题栏我们需要自己实现窗口拖拽功能def mousePressEvent(self, event): if event.button() Qt.LeftButton: self.drag_position event.globalPos() - self.frameGeometry().topLeft() event.accept() def mouseMoveEvent(self, event): if hasattr(self, drag_position) and event.buttons() Qt.LeftButton: self.move(event.globalPos() - self.drag_position) event.accept()这段代码记录了鼠标按下时的位置并在移动时计算窗口应该移动到的位置。实测下来非常流畅和普通窗口的拖拽体验一致。4. 获取系统监控数据4.1 使用psutil获取基础信息psutil库是我们获取系统信息的主力工具它提供了跨平台的系统信息获取接口import psutil # 获取CPU使用率 cpu_percent psutil.cpu_percent(interval1) # 获取内存信息 mem psutil.virtual_memory() mem_percent mem.percent mem_used mem.used / (1024 ** 3) # 转换为GB # 获取网络速度 net_io psutil.net_io_counters() bytes_sent net_io.bytes_sent bytes_recv net_io.bytes_recv这里有个小技巧获取CPU使用率时设置interval1可以让第一次调用立即返回有意义的值否则第一次调用通常会返回0。4.2 计算实时网速计算网速需要记录前后两次的数据然后计算差值class NetSpeedMonitor: def __init__(self): self.last_bytes_sent 0 self.last_bytes_recv 0 def get_speed(self): current psutil.net_io_counters() sent_speed current.bytes_sent - self.last_bytes_sent recv_speed current.bytes_recv - self.last_bytes_recv self.last_bytes_sent current.bytes_sent self.last_bytes_recv current.bytes_recv return sent_speed, recv_speed使用时需要定期调用get_speed()比如每秒一次。返回值的单位是字节/秒可以自行转换为KB/s或MB/s。5. 实现数据实时更新5.1 使用QThread避免界面卡顿直接在主线程中循环获取数据会导致界面卡顿我们需要使用QThreadfrom PyQt5.QtCore import QThread, pyqtSignal class MonitorThread(QThread): data_updated pyqtSignal(dict) # 定义信号 def run(self): net_monitor NetSpeedMonitor() while True: # 获取各项数据 cpu_percent psutil.cpu_percent(interval1) mem psutil.virtual_memory() sent_speed, recv_speed net_monitor.get_speed() # 发射信号 self.data_updated.emit({ cpu: cpu_percent, mem: mem.percent, sent: sent_speed, recv: recv_speed }) self.msleep(1000) # 1秒更新一次5.2 在主窗口中使用线程class MonitorWindow(QWidget): def __init__(self): super().__init__() self.initUI() self.start_monitor_thread() def start_monitor_thread(self): self.monitor_thread MonitorThread() self.monitor_thread.data_updated.connect(self.update_data) self.monitor_thread.start() def update_data(self, data): # 更新界面显示 text fCPU: {data[cpu]}%\n text fMEM: {data[mem]}%\n text f↑ {data[sent]/1024:.1f}KB/s\n text f↓ {data[recv]/1024:.1f}KB/s self.label.setText(text)这样我们就实现了一个不卡界面的实时监控悬浮窗。每秒更新一次数据对系统资源的消耗几乎可以忽略不计。6. 高级功能实现6.1 贴边自动隐藏仿照QQ的贴边隐藏效果我们需要检测窗口位置def check_window_position(self): screen_rect QApplication.desktop().availableGeometry() window_rect self.geometry() # 判断是否靠近屏幕边缘 if window_rect.left() 0: self.hide_to_side(left) elif window_rect.right() screen_rect.right(): self.hide_to_side(right) elif window_rect.top() 0: self.hide_to_side(top) def hide_to_side(self, side): # 使用动画实现平滑隐藏 animation QPropertyAnimation(self, bgeometry) animation.setDuration(300) # 300毫秒动画 if side left: animation.setEndValue(QRect(-self.width()5, self.y(), self.width(), self.height())) elif side right: x QApplication.desktop().width() - 5 animation.setEndValue(QRect(x, self.y(), self.width(), self.height())) elif side top: animation.setEndValue(QRect(self.x(), -self.height()5, self.width(), self.height())) animation.start()对应的还需要实现鼠标移入时显示窗口的功能def enterEvent(self, event): if self.isHidden() or self.geometry().width() 10: self.show_normal() def show_normal(self): animation QPropertyAnimation(self, bgeometry) animation.setDuration(300) animation.setEndValue(QRect(self.normal_x, self.y(), self.width(), self.height())) animation.start()6.2 右键菜单功能添加一个简单的右键菜单def contextMenuEvent(self, event): menu QMenu(self) exit_action menu.addAction(退出) color_action menu.addAction(更换颜色) opacity_action menu.addAction(调整透明度) action menu.exec_(self.mapToGlobal(event.pos())) if action exit_action: self.close() elif action color_action: self.change_color() elif action opacity_action: self.adjust_opacity() def change_color(self): color QColorDialog.getColor() if color.isValid(): self.label.setStyleSheet(fcolor: {color.name()}; font-size: 16px;) def adjust_opacity(self): opacity, ok QInputDialog.getDouble(self, 透明度, 输入透明度(0.1-1.0), self.windowOpacity(), 0.1, 1.0, 1) if ok: self.setWindowOpacity(opacity)7. 打包发布7.1 使用PyInstaller打包pyinstaller -F -w -i monitor.ico monitor.py参数说明-F打包成单个exe文件-w不显示命令行窗口-i指定图标文件7.2 减小打包体积Python打包出来的exe通常比较大可以尝试以下方法减小体积使用UPX压缩pyinstaller -F -w --upx-dirupx_dir -i monitor.ico monitor.py创建虚拟环境只安装必要的包使用--exclude-module排除不需要的模块不过实测下来即使用尽各种优化方法一个简单的Qt程序打包后也至少有10MB左右。这是Python GUI程序的通病如果对体积特别敏感可能需要考虑其他语言实现。8. 最终效果与优化建议完成后的悬浮窗应该具备以下功能实时显示CPU、内存使用率显示上下行网速支持拖拽移动贴边自动隐藏右键菜单调整外观我在实际使用中发现几个优化点数据格式化网速超过1MB/s时自动切换单位显示预警功能CPU或内存超过阈值时改变文字颜色历史记录显示最近几分钟的资源使用曲线多显示器支持正确处理跨显示器的情况这些进阶功能实现起来也不复杂有兴趣的读者可以自行扩展。完整代码我已经上传到GitHub包含详细注释和几个预设的样式主题。

相关新闻

量化交易核心模型:从CAPM到多因子模型的实战解析

量化交易核心模型:从CAPM到多因子模型的实战解析

1. 从CAPM到多因子模型:量化交易的进化之路我第一次接触CAPM模型是在研究生时期,当时教授用"买奶茶"的比喻让我瞬间理解了β值的含义:如果整个奶茶市场涨价10%,而某品牌奶茶价格总是涨15%,它的β值就是1.5。…

2026/7/15 4:26:52阅读更多 →
从供电到信号:深入解析2线制与3线制4-20mA电流环的设计差异与应用选型

从供电到信号:深入解析2线制与3线制4-20mA电流环的设计差异与应用选型

1. 4-20mA电流环的工业生存法则第一次接触4-20mA电流环是在某化工厂的DCS系统改造项目。当时现场有个压力变送器距离控制室足足有800米,施工队直接拉了两根0.5mm的铜芯线。老师傅拍着胸脯说:"用这个电流环,信号要是飘了,我请…

2026/7/15 4:26:52阅读更多 →
倍福嵌入式控制器PLC系列选型与应用场景解析

倍福嵌入式控制器PLC系列选型与应用场景解析

1. 倍福嵌入式控制器PLC系列概述倍福(Beckhoff)的嵌入式控制器PLC系列是工业自动化领域的明星产品,它们将PC技术与模块化I/O系统完美结合,形成了独特的"工业PCEtherCAT"架构。我第一次接触CX8000控制器是在2015年的一个…

2026/7/15 4:26:52阅读更多 →
影刀RPA 影刀流程的单元测试方法:不靠试跑靠验证

影刀RPA 影刀流程的单元测试方法:不靠试跑靠验证

影刀RPA 影刀流程的单元测试方法:不靠试跑靠验证 作者:林焱 大多数人验证流程的方法是:跑一遍,看看结果对不对。这在小流程中没问题,流程一大、分支一多,靠"试跑"验证效率极低。更专业的做法是单…

2026/7/15 5:21:57阅读更多 →
影刀RPA 影刀中的SQL查询大全:从简单查询到多表联查

影刀RPA 影刀中的SQL查询大全:从简单查询到多表联查

影刀RPA 影刀中的SQL查询大全:从简单查询到多表联查 作者:林焱 影刀内置了SQLite指令,但很多新手只会最简单的SELECT *。这篇把RPA场景中最常用的SQL语句整理出来——不是数据库教科书,而是你在写影刀流程时打开就能抄的速查表。…

2026/7/15 5:21:57阅读更多 →
DS90UB662-Q1多路视频流合并:CSI-2转发模式详解与工程实践

DS90UB662-Q1多路视频流合并:CSI-2转发模式详解与工程实践

1. 项目概述:多路视频流合并的挑战与DS90UB662-Q1的解决方案在嵌入式视觉系统,尤其是汽车电子领域,我们常常面临一个核心挑战:如何将来自多个图像传感器(比如环视系统的四个鱼眼摄像头)的视频流&#xff0c…

2026/7/15 5:21:57阅读更多 →
Spring IOC 控制反转

Spring IOC 控制反转

一句话 IOC 是把对象的创建和依赖管理权从代码里转移到了 Spring 容器,开发者不再手动 new 对象和 set 依赖,而是由容器统一管理并注入。 1. 什么是 IOC 传统方式:UserService service new UserService();service.setUserDao(new UserDao()…

2026/7/15 5:21:57阅读更多 →
影刀RPA 异常处理的分层设计:子流程级、步骤级、操作级的三层防线

影刀RPA 异常处理的分层设计:子流程级、步骤级、操作级的三层防线

影刀RPA 异常处理的分层设计:子流程级、步骤级、操作级的三层防线 作者:林焱 异常处理是RPA流程稳定性的最后一道防线。没有异常处理的流程,一个报错就全盘崩溃;异常处理太粗的流程,错误信息被吞掉,出问题…

2026/7/15 5:21:57阅读更多 →
Windows Home Server 2011安装指南:兼容性、驱动与家庭服务器部署

Windows Home Server 2011安装指南:兼容性、驱动与家庭服务器部署

如果你在整理旧设备时翻出一台还能开机的老电脑,或者想用最低成本搭建一个家庭文件备份和远程访问环境,可能会想到十年前那个专为家庭设计的服务器系统——Windows Home Server 2011。虽然它早已在2016年停止支持,但在某些特定场景下&#xf…

2026/7/15 5:16:57阅读更多 →
VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异

VSCode TypeScript 环境配置对比:全局安装 vs 项目本地安装的4个关键差异当你在VSCode中启动一个新的TypeScript项目时,第一个技术决策往往从安装方式开始。这个看似简单的选择——全局安装还是项目本地安装——实际上会深刻影响你的开发流程、团队协作和…

2026/7/14 4:56:14阅读更多 →
智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手

智慧树刷课插件:5分钟实现自动化学习的智能助手 【免费下载链接】zhihuishu 智慧树刷课插件,自动播放下一集、1.5倍速度、无声 项目地址: https://gitcode.com/gh_mirrors/zh/zhihuishu 智慧树刷课插件是一款专为智慧树在线教育平台设计的Chrome浏…

2026/7/14 2:55:05阅读更多 →
Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案

Steam创意工坊下载器WorkshopDL:跨平台游戏模组获取的终极解决方案 【免费下载链接】WorkshopDL WorkshopDL - The Best Steam Workshop Downloader 项目地址: https://gitcode.com/gh_mirrors/wo/WorkshopDL 你是否在GOG或Epic Games Store购买了心仪的游戏…

2026/7/14 6:17:41阅读更多 →
AI框架决定企业AI能走多远

AI框架决定企业AI能走多远

企业AI建设的第一性原理 企业搞AI,最关键的决定是什么?不是选哪家大模型,不是先做哪个场景,不是招多少AI人才——而是选哪个AI开发框架。 为什么?因为框架决定了企业AI能力的"天花板"。选对了框架&#xff0…

2026/7/15 0:01:30阅读更多 →
Java企业为什么需要AI框架

Java企业为什么需要AI框架

Java企业在AI时代的尴尬处境 Java是全球企业级应用开发的主流语言——全球超过一半的企业系统跑在Java上。但在AI浪潮面前,很多Java企业感到尴尬:大模型的接口是各种语言的,AI开发社区以其他语言为主流,似乎Java在AI时代"掉队…

2026/7/15 0:01:30阅读更多 →
CC3230x嵌入式开发实战:SD主机、定时器与低功耗模式深度解析

CC3230x嵌入式开发实战:SD主机、定时器与低功耗模式深度解析

1. 项目概述:为什么需要关注CC3230x的SD主机、定时器与低功耗?在物联网和嵌入式设备开发领域,我们常常面临一个核心矛盾:设备需要具备强大的连接能力、可靠的数据存储和实时控制功能,同时又必须严格控制功耗以延长电池…

2026/7/15 0:01:30阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/14 15:07:30阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/14 4:45:36阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/14 2:42:17阅读更多 →