mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-28 22:30:49 +08:00
docs(Widget Tree): provide data lost from end of doc (#9158)
This commit is contained in:
@@ -7,17 +7,17 @@ Widget Tree
|
||||
Parents and Children
|
||||
********************
|
||||
|
||||
LVGL stores widgets in a parent-child structure (tree).
|
||||
The root element is the screen, which has no parent.
|
||||
LVGL stores Widgets in a parent-child structure (tree).
|
||||
The root element is the Screen, which has no parent.
|
||||
|
||||
When a widget is created, a pointer to its parent is passed to the create function.
|
||||
When a Widget is created, a pointer to its parent is passed to the create function.
|
||||
|
||||
LVGL provides many useful functions to modify the widget tree and get information about it:
|
||||
LVGL provides many useful functions to modify the Widget tree and get information about it:
|
||||
|
||||
- :cpp:expr:`lv_obj_get_screen(widget)`: Get a widget's screen ("root" parent).
|
||||
- :cpp:expr:`lv_obj_get_parent(widget)`: Get the widget's current parent.
|
||||
- `lv_obj_set_parent(widget, new_parent)`: Move the widget to a new parent.
|
||||
The widget will become the top-most (last/youngest) child of the new parent.
|
||||
- :cpp:expr:`lv_obj_get_screen(widget)`: Get a Widget's screen ("root" parent).
|
||||
- :cpp:expr:`lv_obj_get_parent(widget)`: Get the Widget's current parent.
|
||||
- `lv_obj_set_parent(widget, new_parent)`: Move the Widget to a new parent.
|
||||
The Widget will become the top-most (last/youngest) child of the new parent.
|
||||
- :cpp:expr:`lv_obj_get_child(parent, idx)`: Return a specific child of a parent.
|
||||
Some examples for ``idx``:
|
||||
|
||||
@@ -26,13 +26,13 @@ LVGL provides many useful functions to modify the widget tree and get informatio
|
||||
- ``-1``: get the last created child
|
||||
- :cpp:expr:`lv_obj_get_child_by_type(parent, idx, &lv_slider_class)`: Similar to :cpp:expr:`lv_obj_get_child` but filters to children
|
||||
with a given type.
|
||||
- :cpp:expr:`lv_obj_find_by_name(parent, "text")`: Find a widget with a given name under a parent. It does not have to be a direct child.
|
||||
- :cpp:expr:`lv_obj_get_child_by_name(parent, "container/button/text")`: Get a widget by navigating a path using parent names (separated by ``/``).
|
||||
- :cpp:expr:`lv_obj_get_index(widget)`: Return the index of the widget in its parent.
|
||||
- :cpp:expr:`lv_obj_find_by_name(parent, "text")`: Find a Widget with a given name under a parent. It does not have to be a direct child.
|
||||
- :cpp:expr:`lv_obj_get_child_by_name(parent, "container/button/text")`: Get a Widget by navigating a path using parent names (separated by ``/``).
|
||||
- :cpp:expr:`lv_obj_get_index(widget)`: Return the index of the Widget in its parent.
|
||||
It is equivalent to the number of older siblings in the parent.
|
||||
- :cpp:expr:`lv_obj_move_to_index(widget, idx)`: Move the widget to a specified index.
|
||||
- :cpp:expr:`lv_obj_move_to_index(widget, idx)`: Move the Widget to a specified index.
|
||||
``0`` is the oldest child's position, ``-1`` is the youngest.
|
||||
- :cpp:expr:`lv_obj_swap(widget1, widget2)`: Swap the positions of two widgets.
|
||||
- :cpp:expr:`lv_obj_swap(widget1, widget2)`: Swap the positions of two Widgets.
|
||||
|
||||
To iterate through a parent widget's children:
|
||||
|
||||
@@ -52,23 +52,26 @@ To iterate through a parent widget's children:
|
||||
Names
|
||||
*****
|
||||
|
||||
When a widget is created, its reference can be stored in an :cpp:expr:`lv_obj_t *` pointer
|
||||
variable. To use this widget in multiple places in the code, the variable can be passed
|
||||
When a Widget is created, its reference can be stored in an :cpp:expr:`lv_obj_t *` pointer
|
||||
variable. To use this Widget in multiple places in the code, the variable can be passed
|
||||
as a function parameter or made global. However, this approach has some drawbacks:
|
||||
|
||||
- Using global variables adds names to the global namespace and is thus generally not recommended.
|
||||
- It's not scalable. Passing references to 20 widgets as function parameters is not ideal.
|
||||
- Tracking whether a widget still exists or has been deleted requires extra logic and can be tricky.
|
||||
- It's not scalable. Passing references to 20 Widgets as function parameters is not ideal.
|
||||
- Tracking whether a Widget still exists or has been deleted requires extra logic and can be tricky.
|
||||
|
||||
|
||||
.. _tree_setting_names:
|
||||
|
||||
Setting Names
|
||||
-------------
|
||||
|
||||
To address these issues, LVGL introduces a powerful widget naming system that can be enabled
|
||||
To address these issues, LVGL introduces a powerful Widget naming system that can be enabled
|
||||
by setting ``LV_USE_OBJ_NAME`` in ``lv_conf.h``.
|
||||
|
||||
A custom name can be assigned using :cpp:expr:`lv_obj_set_name(obj, "name")` or
|
||||
:cpp:expr:`lv_obj_set_name_static(obj, "name")`. The "static" variant requires that the passed
|
||||
name remains valid while the widget exists, since only the pointer is stored. Otherwise, LVGL will
|
||||
name remains valid while the Widget exists, since only the pointer is stored. Otherwise, LVGL will
|
||||
allocate memory to store a copy of the name.
|
||||
|
||||
If a name ends with ``#``, LVGL will automatically replace it with an index based on the
|
||||
@@ -83,7 +86,7 @@ Below is an example showing how manually and automatically assigned names are re
|
||||
|
||||
- ``lv_label`` with no name: "lv_label_0"
|
||||
- ``lv_label`` named ``"title"``: "title"
|
||||
- ``lv_label`` with no name: "lv_label_1" (It's the third label, but custom-named widgets are not counted)
|
||||
- ``lv_label`` with no name: "lv_label_1" (It's the third label, but custom-named Widgets are not counted)
|
||||
|
||||
- ``lv_obj`` container named ``"buttons"``:
|
||||
|
||||
@@ -97,6 +100,12 @@ Below is an example showing how manually and automatically assigned names are re
|
||||
- ``lv_button`` named ``mybtn_#``: "mybtn_2"
|
||||
- ``lv_button`` named ``mybtn_#``: "mybtn_3"
|
||||
|
||||
Note that these indices are "fluid", meaning if "mybtn_2" above is deleted, the button
|
||||
previously known as "mybtn_3" will thereafter be known as "mybtn_2", since the
|
||||
indices are resolved *when names are being found by name*, not when they are set.
|
||||
Keep this in mind when Finding Widgets as described below.
|
||||
|
||||
|
||||
Finding Widgets
|
||||
---------------
|
||||
|
||||
@@ -104,4 +113,28 @@ Widgets can be found by name in two ways:
|
||||
|
||||
1. **Get a direct child by name** using :cpp:expr:`lv_obj_get_child_by_name(parent, "child_name")`.
|
||||
Example:
|
||||
:cpp:expr:`lv_obj_get_child_by_name(header, "title")`
|
||||
:cpp:expr:`lv_obj_get_child_by_name(header, "title")`.
|
||||
You can also use a path to find nested children:
|
||||
:cpp:expr:`lv_obj_get_child_by_name(cont, "buttons/mybtn_2")`.
|
||||
|
||||
2. **Find a descendant at any level** using :cpp:expr:`lv_obj_find_by_name(parent, "child_name")`.
|
||||
Example:
|
||||
:cpp:expr:`lv_obj_find_by_name(cont, "mybtn_1")`
|
||||
Note that ``"mybtn_1"`` is a child of ``cont`` at any level, not necessarily a
|
||||
direct child. This is useful when you want to ignore the hierarchy and search by
|
||||
name alone.
|
||||
|
||||
Since both functions start searching from a specific parent, it's possible to have
|
||||
multiple Widget subtrees with identical names under different parents.
|
||||
|
||||
For example, if ``my_listitem_create(parent)`` creates a Widget named ``"list_item_#"``
|
||||
with direct children ``"icon"``, ``"title"``, ``"ok_button"``, and ``"lv_label_0"``,
|
||||
and it is called 10 times, a specific ``"ok_button"`` can be found like this:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
lv_obj_t * item = lv_obj_find_by_name(lv_screen_active(), "list_item_5");
|
||||
lv_obj_t * ok_btn = lv_obj_find_by_name(item, "ok_button");
|
||||
|
||||
// Or
|
||||
lv_obj_t * ok_btn = lv_obj_get_child_by_name(some_list_container, "list_item_5/ok_button");
|
||||
|
||||
Reference in New Issue
Block a user