跳转到内容

图形显示菜单

该组件提供了在图形显示屏上设置层次菜单的基础设施。这为用户提供了一种交互方法来显示标签、控制 ESPHome 节点上本地可用的 switchselectnumber 等实体,无需网络连接。

该组件实现了 显示菜单 组件,提供了一个主要旨在通过带按钮的旋转编码器或五键摇杆控制器控制的层次菜单。

该组件需要连接到支持 ESPHome 渲染引擎的显示屏实例,如 电子纸显示屏OLED 显示屏

# 示例配置
graphical_display_menu:
id: my_graphical_display_menu
display: my_display_component
on_redraw:
then:
component.update: my_display_component
active: false
mode: rotary
items:
...

配置变量:

  • id (可选, ID):手动指定用于代码生成的 ID。

  • display (可选, ID):要渲染到的显示屏 ID。有关更多详细信息,请参阅 绘制模式

  • font (必需, 字体):指定要使用的字体

  • foreground_color (可选, 颜色):指定要使用的前景色。默认为 COLOR_ON

  • background_color (可选, 颜色):指定要使用的背景色。默认为 COLOR_OFF

自动化:

  • on_redraw (可选, 自动化):当菜单需要重绘时执行的自动化。如果您的显示屏刷新率较慢,这会很有用。例如,使用 display_interval: never 的电子墨水显示屏。

其他配置在 显示菜单 组件中描述。

当指定 display 时,菜单将在初始化过程中创建一个 页面。调用时它将渲染到整个显示屏。当您可能希望将显示屏用于其他目的,但响应用户交互显示菜单时,这很有用。

NOTE

弹出模式要求您的显示屏使用 页面。如果您使用绘制 lambda 而没有页面,它将无法按预期工作。相反,您必须使用高级模式

如果在设置菜单时未指定 display,您将负责控制菜单的绘制。这也允许您将菜单渲染到比可用屏幕大小更小的部分。在您希望将菜单作为更大用户界面一部分显示的情况下可能很有用(例如渲染传感器图形和旁边的控制菜单)

# 示例配置
graphical_display_menu:
- id: my_menu
# 注意:未指定 display
active: true
display:
- platform: waveshare_epaper
id: my_display_component
pages:
- id: advanced_drawing_mode_page
lambda: |-
const auto display_width = it.get_width();
const auto display_height = it.get_height();
auto half_display_width = (int)(display_width / 2.0f);
// 这将菜单渲染到屏幕右半部分,左半部分用于其他绘制目的
// 参数: it.menu(x, y, menu, width, height);
it.menu(half_display_width, 0, id(my_menu), half_display_width, display_height);

如果您希望模拟弹出模式,以下示例将模拟相同的行为。如果您使用不带 页面 的显示屏,或者您有其他需要控制菜单渲染方式和位置的需求,这可能很有用。

graphical_display_menu:
id: my_menu
items:
# ... 其他项目在这里 ...
# 一个退出菜单项(或其他机制)调用 display_menu.hide
- type: command
on_value:
then:
- display_menu.hide: my_menu
display:
- platform: ..
lambda: |-
const auto width = it.get_width();
const auto height = it.get_height();
if (id(my_menu).is_active()) {
it.menu(0, 0, id(my_menu), width, height);
} else {
it.print(0, 0, id(font), "菜单已隐藏,其他绘制内容将放在这里");
}

默认情况下,带有值的菜单项将在一对括号之间渲染。这可以通过 menu_item_value 参数控制。

  • menu_item_value (可选, 模板):指定如何为具有值的菜单项(例如选择器、数值)渲染值。默认将值渲染为”(value here)“。接收 MenuItemValueArguments 作为参数 it
graphical_display_menu:
menu_item_value: !lambda |-
// 正常情况下将菜单项值渲染为 "My menu label ~my value here"",编辑模式下为 "My menu label *my value here*"
std::string label = " ";
if (it->is_item_selected && it->is_menu_editing) {
label.append("*");
label.append(it->item->get_value_text());
label.append("*");
} else {
label.append("~");
label.append(it->item->get_value_text());
label.append("~");
}
return label;

NOTE

确保您在 menu_item_value 中使用的所有字符都是您的 字体 可用的字形

下面的示例是一个更完整的示例,展示如何使用旋转编码器和按钮来显示/隐藏菜单并在可用选项之间移动

# 示例配置
display:
- platform: waveshare_epaper
id: my_display_component
pages:
- id: graph_page
lambda: |-
it.print(0, 0, id(my_font), "我的菜单当前未激活");
font:
- file: ...
id: my_font
size: 16
graphical_display_menu:
id: my_graphical_display_menu
display: my_display_component
on_redraw:
then:
component.update: my_display_component
active: false
mode: rotary
items:
- type: Label
text: 菜单项 1
- type: Label
text: 菜单项 2
# 旋转编码器提供导航
sensor:
- platform: rotary_encoder
...
filters:
debounce: 30ms
on_anticlockwise:
- display_menu.up: my_graphical_display_menu
on_clockwise:
- display_menu.down: my_graphical_display_menu
# 使用去抖动的 GPIO 按钮进行"点击"
binary_sensor:
- platform: gpio
...
filters:
- delayed_on: 30ms
- delayed_off: 30ms
on_press:
- if:
condition:
display_menu.is_active: my_graphical_display_menu
then:
- display_menu.enter: my_graphical_display_menu
else:
- display_menu.show: my_graphical_display_menu