- 桌面应用
【免费下载链接】yasb
A highly configurable Windows status bar written in Python.
本指南完整讲解 yasb(一款高度可配置的 Windows 状态栏,使用 Python 编写)中 Memory Widget 的全部能力:实时显示系统物理内存(RAM)与交换内存(Swap / 页面文件)使用情况,支持自定义告警阈值、实时使用率直方图与环形进度指示器,点击组件可弹出包含详细内存分配统计的菜单。阅读完本文,你将掌握label格式化占位符的完整用法、memory_thresholds四级状态语义、progress_bar环形/线性进度条的进阶配置,以及menu弹出菜单(含实时图表与统计网格)的定制方法,并了解这些能力在 yasb 源码中的底层实现原理。
一、组件总览与定位
Memory Widget 是 yasb 内置的状态栏组件之一,用于在状态栏上实时展示系统内存状况。根据 Memory Widget 文档-Memory.md),它具备以下核心特性:
- 实时显示系统 RAM 与 Swap 内存使用量;
- 自定义告警阈值(
low/medium/high/critical四级状态); - 实时使用率直方图(由
{histogram}占位符驱动的块状字符条); - 环形或线性的进度指示器;
- 点击后弹出的内存详情菜单(含使用率历史折线图与统计网格)。
在 yasb 的配置体系中,Memory Widget 的type固定为"yasb.memory.MemoryWidget",其实现位于 src/core/widgets/yasb/memory.py,数据采集与校验模型分别在 src/core/widgets/services/memory/memory_api.py 与 src/core/validation/widgets/yasb/memory.py 中。内置预设MEMORY_WIDGET定义于 src/core/setup/widgets_config.py#L236-L265,可作为快速上手的参考起点。
环境前提:Memory Widget 依赖 Windows 原生 API(
GlobalMemoryStatusEx、GetPerformanceInfo、PDH 与NtQuerySystemInformation)采集数据,因此仅能在 Windows 系统上正常工作。
二、组件接入:在状态栏中启用 Memory Widget
在将 Memory Widget 接入状态栏前,需要先了解 yasb 的配置文件结构。配置文件使用 YAML 格式,命名为config或config.yaml,有效位置为C:/Users/{username}/.config/yasb/(或由环境变量YASB_CONFIG_HOME指定的目录),详见 Configuration.md。
在配置文件中,bars的每个状态栏通过widgets.left/widgets.center/widgets.right三个区域引用组件名,例如:
bars: status-bar: screens: ['*'] # 显示在所有未被其他 bar 分配的屏幕上 widgets: left: ["clock"] center: ["cpu"] right: ["memory"] # 将 memory 组件放入右侧区域 widgets: memory: type: "yasb.memory.MemoryWidget" options: # ... 详见下文各配置小节与组件对应的widgets配置块必须以type: "yasb.memory.MemoryWidget"声明,否则无法被 widgets_config.py 中的组件注册表正确解析。
三、核心选项速查表
Memory Widget 的全部选项定义在 src/core/validation/widgets/yasb/memory.py 的MemoryConfig模型中,下表汇总了每个选项的类型、默认值与说明:
| 选项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
label | string | '\uf4bc {virtual_mem_free}/{virtual_mem_total}' | 主显示格式串,展示空闲与总虚拟内存(物理内存) |
label_alt | string | '\uf4bc VIRT: {virtual_mem_percent}% SWAP: {swap_mem_percent}%' | 备用格式串,展示虚拟内存与交换内存百分比 |
class_name | string | "" | 附加的 CSS 类名,用于自定义样式 |
update_interval | integer | 5000 | 数据刷新间隔(毫秒),有效范围 1000–60000 |
callbacks | dict | {'on_left': 'toggle_label', 'on_middle': 'do_nothing', 'on_right': 'do_nothing'} | 鼠标事件回调配置 |
histogram_icons | list | ["\u2581", "\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"] | 直方图块字符图标(必须恰好 9 个) |
memory_thresholds | dict | {'low': 25, 'medium': 50, 'high': 90} | 内存占用等级阈值 |
progress_bar | dict | 见下方小节 | 进度条设置 |
hide_decimal | boolean | false | 是否隐藏数值的小数位 |
menu | dict | 见下方小节 | 弹出菜单配置(含图表与统计) |
keybindings | list | [] | 组件快捷键绑定(可选) |
注意:文档表格中的
update_interval描述为"0 到 60000",但校验模型 memory.py#L56 实际约束为ge=1000, le=60000(即最小 1000ms);设置0不会被接受。当update_interval > 0时才启动后台采集线程,因此实际有效下限为 1000ms。
四、示例配置(完整版)
以下是 Memory Widget 文档-Memory.md) 给出的完整 YAML 示例,包含中文注释与取值说明:
memory: type: "yasb.memory.MemoryWidget" options: label: "<span>\uf4bc</span> {virtual_mem_free}/{virtual_mem_total}" label_alt: "<span>\uf4bc</span> VIRT: {virtual_mem_percent}% SWAP: {swap_mem_percent}%" update_interval: 5000 callbacks: on_left: "toggle_label" on_right: "toggle_menu" memory_thresholds: low: 25 medium: 50 high: 90 histogram_icons: - "\u2581" # 0% - "\u2581" # 10% - "\u2582" # 20% - "\u2583" # 30% - "\u2584" # 40% - "\u2585" # 50% - "\u2586" # 60% - "\u2587" # 70% - "\u2588" # 80%+ menu: enabled: true show_graph: true show_graph_grid: true graph_history_size: 60内置预设 widgets_config.py#L236-L265 给出的实践版本还展示了另一种常见组合:hide_decimal: True(隐藏小数)、on_left: "toggle_menu"(左键弹出菜单)、on_right: "toggle_label"(右键切换标签)、menu.alignment: "center"(菜单水平居中),并分别使用<span>\ue9d9</span>与<span>\uefc5</span>作为图标字体字符。你可以根据自己的习惯选择左键/右键绑定toggle_menu或toggle_label。
五、label 格式化:全部可用占位符
label与label_alt均为格式串,其中可嵌入占位符,组件每次刷新时会将占位符替换为实际采集值。占位符替换逻辑实现在 memory.py#L169-L180 的label_options字典中。完整的可用占位符如下:
| 占位符 | 含义 | 替换规则 |
|---|---|---|
{virtual_mem_free} | 空闲物理内存 | 以人类可读大小显示(如3.1GB) |
{virtual_mem_percent} | 物理内存使用率(%) | 数值(受hide_decimal影响取整) |
{virtual_mem_total} | 物理内存总量 | 人类可读大小 |
{virtual_mem_avail} | 可用物理内存 | 人类可读大小 |
{virtual_mem_used} | 已用物理内存 | 人类可读大小 |
{virtual_mem_outof} | 已用 / 总量 | 组合串,如4.2GB / 16.0GB |
{swap_mem_free} | 空闲交换内存 | 人类可读大小 |
{swap_mem_percent} | 交换内存使用率(%) | 数值 |
{swap_mem_total} | 交换内存总量 | 人类可读大小 |
{histogram} | 直方图块 | 由histogram_icons与当前使用率换算出的 1 个字符 |
两点实践建议:
- 文档中的
<span>\uf4bc</span>为图标字体字符(Nerd Font / Segoe MDL2 类图标),会被识别为独立icon元素,便于单独设置 CSS 样式(详见第八节样式)。 hide_decimal: true时,百分比占位符会被取整、大小占位符使用%.0f格式化;false(默认)时大小使用%.1f保留 1 位小数。此逻辑在 memory.py#L163-L167 中体现。
关于{virtual_mem_percent}的换算细节
virtual_mem_percent并非直接由 Windows API 提供,而是由采集层计算得出:在 memory_api.py#L151-L154 中,MemoryAPI.virtual_memory()通过GlobalMemoryStatusEx取得ullTotalPhys与ullAvailPhys后,以used = total - available、percent = round((used / total) * 100, 1)计算并保留 1 位小数。因此该值本质上是"(总量 − 可用)/ 总量",与任务管理器的内存占用口径一致。
六、内存阈值与四级状态样式
memory_thresholds用于将内存使用率映射为语义化状态,从而驱动 CSS 状态类切换。默认值为{'low': 25, 'medium': 50, 'high': 90},校验模型 memory.py#L12-L15 将每个阈值限制在 0–100 之间。
判定逻辑实现在 memory.py#L219-L226 的_get_virtual_memory_threshold方法中:
- 使用率
<= low→status-low low < 使用率 <= medium→status-mediummedium < 使用率 <= high→status-high使用率 > high→status-critical
当使用率变化导致状态级别变化时,组件会为 label 元素更新class属性(形如label status-high)并调用refresh_widget_style强制刷新样式,相关代码见 memory.py#L201-L206。这实现了"内存占用越高,颜色自动变化"的动态告警效果。
七、直方图(histogram_icons)
histogram_icons是一组恰好 9 个字符的列表,默认值为["\u2581", "\u2581", "\u2582", "\u2583", "\u2584", "\u2585", "\u2586", "\u2587", "\u2588"](即 Unicode 区块字符▁▁▂▃▄▅▆▇█),从左到右代表 0% 到 80%+ 的占用程度。校验模型 memory.py#L57-L61 强制min_length=9, max_length=9,因此数量不可增删。
在label或label_alt中放入{histogram}占位符即可显示直方图。换算逻辑见 memory.py#L228-L233 的_get_histogram_bar:将当前使用率(0–100)线性映射到图标列表下标,并做上下界裁剪。例如使用率 50% 会映射到下标 4(约▄),接近满内存时映射到█。
八、进度条(progress_bar)进阶配置
progress_bar提供环形与线性的可视化进度指示。默认配置为{'enabled': false, 'progress_type': 'circular', 'position': 'left', 'size': 18, 'thickness': 3, 'radius': 0, 'color': '#00C800', 'background_color': '#3C3C3C', 'animation': true},各字段含义:
| 字段 | 说明 | 约束 |
|---|---|---|
enabled | 是否启用进度条 | 布尔 |
progress_type | 进度条形态 | "circular"、"linear_horizontal"、"linear_vertical"三选一 |
position | 在组件内容中的位置 | "left"或"right" |
size | 长度(线性)或直径(环形) | 最小 1,最大 200 |
thickness | 线条粗细 | 最小 1,最大 100 |
radius | 线性进度条的圆角半径 | 最小 0,最大 100 |
color | 颜色,支持单色或渐变 | 单色如"#57948a";渐变如["#57948a", "#ff0000"] |
background_color | 背景色 | 十六进制颜色 |
animation | 是否平滑过渡进度值 | 布尔 |
校验模型见 memory.py#L18-L27。底层绘制实现在 src/core/utils/progress_bar.py:
- 环形模式:背景绘制完整的 360° 圆弧,进度弧从 90° 起按使用率比例逆时针延伸;颜色配置为列表时会使用
QConicalGradient绘制圆锥渐变弧线(progress_bar.py#L69-L80)。 - 线性模式:水平或垂直填充,使用
QLinearGradient支持渐变;radius控制圆角,并通过裁剪保证进度区域的圆角与背景一致(progress_bar.py#L126-L152)。 - 动画:启用时通过
QPropertyAnimation(400ms、OutCubic 缓动)平滑过渡,且当数值变化小于 0.9% 时跳过动画以避免无效刷新(progress_bar.py#L154-L171)。
进度条的取值来源于物理内存使用率:在 memory.py#L182-L188 中,启用后每次数据刷新都会调用progress_widget.set_value(virtual_mem.percent),并根据position决定插入到容器布局的左侧或右侧。
九、弹出菜单(menu):图表与统计网格
当menu.enabled: true且绑定了toggle_menu回调时,点击组件(或触发快捷键)会弹出详情菜单。菜单由 src/core/utils/stat_popup.py 中的PinnablePopup构建,包含标题栏(可固定/拖动)、使用率历史折线图和统计网格三部分。menu全部配置项如下:
| 字段 | 默认值 | 说明 |
|---|---|---|
enabled | false | 是否启用弹出菜单 |
blur | true | 菜单背景是否启用模糊 |
round_corners | true | 菜单是否圆角 |
round_corners_type | "normal" | 圆角类型:"normal"或"small" |
border_color | "System" | 菜单边框颜色 |
alignment | "right" | 菜单相对组件的水平对齐:"left"、"center"、"right" |
direction | "down" | 菜单展开方向:"up"或"down" |
offset_top | 6 | 距组件的垂直偏移(像素) |
offset_left | 0 | 距组件的水平偏移(像素) |
show_graph | true | 是否显示使用率历史图表 |
show_graph_grid | false | 是否在图表上叠加方形网格 |
graph_history_size | 60 | 图表保留的数据点数量,必须介于 10–180 |
pin_icon | "\ue718" | 未固定时固定按钮的图标 |
unpin_icon | "\ue77a" | 已固定时固定按钮的图标 |
校验约束见 memory.py#L35-L49。值得注意的联动关系:
- 固定(pin)功能:点击标题栏的固定按钮后菜单变为"钉住"状态,失焦时不会自动关闭,且可按住左键拖动菜单(stat_popup.py#L23-L102);按钮图标随固定状态在
pin_icon与unpin_icon之间切换。 - 历史数据滚动:组件内部用
collections.deque(maxlen=graph_history_size)维护最近的使用率序列(memory.py#L29),新数据到来时追加并即时更新图表(memory.py#L69-L72、memory.py#L75-L92)。 - 统计网格内容:菜单展示 3 行统计,每行左右各一项,依次为"In use / All memory"、"Cached / Available"、"Swap used / Utilization"(其中 Utilization 直接显示物理内存使用率百分比)。构建逻辑见 memory.py#L102-L127。
- 图表绘制:
GraphWidget将 0–100 的使用率历史绘制为平滑曲线(Catmull-Rom 样条)并带渐变填充,show_graph_grid控制 16px 方形网格的显示,网格颜色由.memory-graph-grid的 CSScolor驱动(stat_popup.py#L105-L247)。 - Cached 数据的来源:
Cached统计项对应 memory_api.py#L111-L128 中_get_cached_bytes()计算的"备用页 + 已修改页"字节数(通过NtQuerySystemInformation的SystemMemoryListInformation与GetPerformanceInfo结合计算),口径与任务管理器一致;API 失败时降级为系统缓存工作集。
十、回调(callbacks)与快捷键
callbacks配置鼠标事件回调,键为on_left、on_middle、on_right。Memory Widget 注册了以下两个自定义回调(memory.py#L36-L37):
toggle_label:在主标签label与备用标签label_alt之间切换显示(memory.py#L209-L217);toggle_menu:打开/关闭内存详情菜单(memory.py#L94-L148)。
默认配置为on_left: "toggle_label"、on_middle: "do_nothing"、on_right: "do_nothing";示例配置常将on_right绑定到toggle_menu,或用左键打开菜单、右键切换标签。do_nothing用于禁用某个按键。
此外,Memory Widget 也支持keybindings快捷键列表,结构为{keys, action, screen?},其中action可填写toggle_label或toggle_menu。例如:
memory: type: "yasb.memory.MemoryWidget" options: keybindings: - keys: "ctrl+shift+m" action: "toggle_menu" screen: "active"通用回调与快捷键机制可参考 Keybindings.md 与 Writing-Widget.md。
十一、样式定制:从 label 状态色到弹出菜单
基础样式骨架
Memory Widget 根元素拥有memory-widget类(叠加class_name自定义类,见 memory.py#L25),文档给出如下样式骨架:
.memory-widget {} .memory-widget .widget-container {} .memory-widget .widget-container .label {} .memory-widget .widget-container .label.alt {} .memory-widget .widget-container .icon {} /* 基于 memory_thresholds 的状态类 */ .memory-widget .widget-container .label.status-low {} .memory-widget .widget-container .label.status-medium {} .memory-widget .widget-container .label.status-high {} .memory-widget .widget-container .label.status-critical {} /* 图标状态类 */ .memory-widget .widget-container .icon.status-low {} .memory-widget .widget-container .icon.status-medium {} .memory-widget .widget-container .icon.status-high {} .memory-widget .widget-container .icon.status-critical {} /* 进度条样式(启用时生效) */ .memory-widget .progress-container {} /* 自定义 class_name 样式 */ .memory-widget.your-class-name {} .memory-widget.your-class-name .label {}状态色实践
以下是一套开箱即用的四级状态配色(低=绿、中=黄、高=橙、临界=红):
.memory-widget { padding: 0 8px; } .memory-widget .widget-container .label { font-size: 13px; color: #cdd6f4; } .memory-widget .widget-container .icon { font-size: 14px; color: #89b4fa; } .memory-widget .widget-container .label.status-low { color: #a6e3a1; /* Green */ } .memory-widget .widget-container .label.status-medium { color: #f9e2af; /* Yellow */ } .memory-widget .widget-container .label.status-high { color: #fab387; /* Orange */ } .memory-widget .widget-container .label.status-critical { color: #f38ba8; /* Red */ } /* 进度条微调:与文字之间保留间距 */ .memory-widget .progress-container { margin-right: 6px; }弹出菜单样式
菜单根元素使用memory-popup类,标题栏、图表、统计网格均有独立类可供定制。文档给出的完整样式如下:
.memory-popup { background-color: rgba(28, 28, 28, 0.7); min-width: 400px; } .memory-popup .header { background: transparent; padding: 12px 16px; } .memory-popup .header .text { font-size: 16px; font-family: "Segoe UI"; color: rgb(255, 255, 255); } .memory-popup .header .pin-btn { font-size: 14px; background: transparent; font-family: "Segoe Fluent Icons"; border: none; padding: 6px; color: rgba(255, 255, 255, 0.6); } .memory-popup .header .pin-btn:hover { color: rgba(255, 255, 255, 0.6); } .memory-popup .header .pin-btn.pinned { color: #ffffff; } /* 图表区域 */ .memory-popup .graph-container { background: transparent; min-height: 64px; } .memory-popup .memory-graph { color: #0f6bff; /* <-- 设置图表折线/填充颜色 */ } .memory-popup .memory-graph-grid { color: rgba(255, 255, 255, 0.05); /* 设置网格线颜色 */ } .memory-popup .graph-title { font-size: 12px; color: rgba(255, 255, 255, 0.5); font-family: 'Segoe UI'; padding: 0px 0px 4px 14px; } /* 统计网格 */ .memory-popup .stats { background: transparent; padding: 16px; } .memory-popup .stats .stat-item { background-color: rgba(255, 255, 255, 0.03); border: 1px solid rgba(255, 255, 255, 0.04); border-radius: 8px; padding: 8px 12px; margin: 8px; } .memory-popup .stats .stat-label { font-size: 13px; color: rgba(255, 255, 255, 0.65); font-family: 'Segoe UI'; font-weight: 400; padding: 6px 4px 2px 4px; } .memory-popup .stats .stat-value { font-size: 20px; font-weight: 700; color: #ffffff; font-family: 'Segoe UI'; padding: 0 4px 12px 4px; }提示:图表颜色与网格线颜色均通过 CSS
color属性控制(stat_popup.py#L193-L247 的绘制逻辑读取前景色),其中网格代理元素使用memory-graph-grid类,若网格色未设置则默认退化为带 30 alpha 的折线色。
十二、数据采集原理:Windows 原生 API 与后台线程
Memory Widget 的数据采集位于 src/core/widgets/services/memory/memory_api.py,采用"前台线程 + 后台采集线程"的异步架构,避免阻塞状态栏 UI:
- 单例后台线程:
MemoryWorker继承自QThread,通过get_instance(update_interval)实现单例;多个 MemoryWidget 实例共享同一个采集线程,且随aboutToQuit信号自动停止(memory_api.py#L210-L247)。组件侧在 memory.py#L44-L52 维护_instances列表并向该线程连接data_ready信号。 - 物理内存:调用
kernel32.GlobalMemoryStatusEx获取MEMORYSTATUSEX结构体(memory_api.py#L143-L164),得到ullTotalPhys、ullAvailPhys并推算出used与percent。 - 交换内存:先通过
psapi.GetPerformanceInfo取得CommitLimit与PhysicalTotal推算页面文件总量(memory_api.py#L166-L198),再使用缓存化的 PDH 计数器\Paging File(_Total)\% Usage获取占用百分比(memory_api.py#L60-L108),PDH 查询只在首次调用时创建并复用,避免频繁开关查询的性能损耗。 - 缓存字节数:
NtQuerySystemInformation(SystemMemoryListInformation)读取备用页(standby)与已修改页(modified)计数,结合GetPerformanceInfo的页大小换算为字节(memory_api.py#L111-L128),供弹出菜单的 Cached 统计项使用。 - 数据分发:线程以
update_interval / 1000秒为周期采集MemoryData(虚拟内存、交换内存、缓存字节三合一快照),通过 Qt 信号投递到主线程,各组件实例更新 label、进度条、历史队列与已打开的菜单(memory.py#L62-L92)。
相关的 Windows 原生结构体与调用约定在 src/core/utils/win32/structs.py 中定义,并在 tests/win32/specs.py 的 ABI 规格中被验证,可供对底层调用感兴趣的读者深入。
十三、常见调优建议
- 刷新频率:
update_interval默认 5000ms。追求实时性可调小(最低 1000ms),但内存采集本身开销极低,一般无需低于 3000ms;注意校验模型不接受小于 1000 的值。 - 直方图与进度条二选一或并用:直方图以 1 个字符嵌入 label,占用空间极小;进度条适合"一眼看趋势"的场景,环形模式建议
size与thickness匹配(如 18/3)。 - 告警阈值:
memory_thresholds的high决定status-critical的触发点,可结合任务管理器的日常占用基线设置;若开启系统缓存占比较高,建议把high设置在 85–92 之间以合理预警。 - 菜单常驻:如需长时间观察内存曲线,将
menu.enabled置为true并在菜单打开后点击固定按钮,失焦不再自动关闭;graph_history_size越大,曲线时间跨度越长(上限 180 点)。 - 多屏布局:与 Configuration.md 中 bar 配置配合,可在不同显示器放置不同组件组合;查看显示器名称可使用
yasbc monitor-information命令(见 CLI.md)。
综上,Memory Widget 既提供了开箱即用的默认配置,也通过label占位符、阈值状态、直方图、进度条与可固定详情菜单提供了充分的定制空间,是 yasb 状态栏中可视化系统资源状态的高频组件。若需为项目编写自定义组件,其回调注册、校验模型与弹窗复用的模式可参考 Writing-Widget.md。
- 桌面应用
【免费下载链接】yasb
A highly configurable Windows status bar written in Python.
相关推荐
Glances 内存监控深入解析:RAM/SWAP 统计字段、趋势指示与告警阈值配置
Glances 内存监控深入解析:RAM/SWAP 统计字段、趋势指示与告警阈值配置 导读 :本文以 Glances 官方文档 docs/aoa/memory.
指标监控监控大盘CLI告警MCP 服务SGLang性能调优终极指南:从诊断到艺术级优化
SGLang性能调优终极指南:从诊断到艺术级优化 在大语言模型服务化的浪潮中,性能瓶颈往往是开发者面临的最大挑战。当你的LLM服务在高峰期响应缓慢,当推理成本超
模型推理服务推理引擎人工智能大模型本地部署多模态Apache DolphinScheduler监控看板设计:关键指标可视化与告警阈值完整指南
Apache DolphinScheduler监控看板设计:关键指标可视化与告警阈值完整指南 Apache DolphinScheduler作为现代化的数据编排
任务调度大数据后端微服务
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考