跳转到内容

图形显示菜单

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

该组件实现了 Display Menu 组件,提供 一个主要通过带按钮的旋转编码器 或五键摇杆控制器进行控制的分层菜单。

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

# Example configuration entry
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 (必填, Font): 指定要使用的字体

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

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

自动化:

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

附加配置在 Display Menu 组件中描述。

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

NOTE

弹出模式要求您的显示屏使用 页面。如果您使用绘制 lambda(没有页面),它将不会 按预期工作。相反,您将不得不使用高级模式

如果在设置菜单时不指定 display,您将负责控制菜单的绘制。这也允许您 将菜单渲染到比可用屏幕尺寸更小的区域。在想要将菜单作为较大用户界面的一部分(例如在传感器图表旁边渲染控制菜单) 的情况下可能会有用。

# Example configuration entry
graphical_display_menu:
- id: my_menu
# Note: No display specified
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);
// This will render the menu to the right half of the screen leaving the left half for other drawing purposes
// Arguments: 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:
# ... other items here ...
# An exit menu item (or some other mechanism) that calls 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 is hidden, other drawing would go here here");
}

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

  • menu_item_value (可选, string, templatable): 指定如何为 具有值的菜单项(例如选择器、数字)渲染值。默认为将值渲染为 “(value here)“。接收 MenuItemValueArguments 作为参数 it。
graphical_display_menu:
menu_item_value: !lambda |-
// Will render your menu item value as "My menu label ~my value here~"" normally and "My menu label *my value here*" when in edit mode
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 中使用的所有字符在您的 字体 中都是可用的字形

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

# Example configuration entry
display:
- platform: waveshare_epaper
id: my_display_component
pages:
- id: graph_page
lambda: |-
it.print(0, 0, id(my_font), "My menu is not currently active");
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: Menu Item 1
- type: Label
text: Menu Item 2
# Rotary encoder to provide navigation
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
# A debounced GPIO push button is used to 'click'
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