1.. _lvgl_basics:
2
3===========
4LVGL Basics
5===========
6
7LVGL (Light and Versatile Graphics Library) is a free and open-source graphics
8library providing everything you need to create an embedded GUI with easy-to-use
9graphical elements, beautiful visual effects, and a low memory footprint.
10
11How does it do this?
12
13
14
15.. _basic_data_flow:
16
17Overview of LVGL's Data Flow
18****************************
19
20.. figure:: /misc/intro_data_flow.png
21    :scale: 75 %
22    :alt:  LVGL Data Flow
23    :align:  center
24    :figwidth:  image
25
26    Overview of LVGL Data Flow
27
28
29You create one :ref:`display` for each physical display panel, create
30:ref:`basics_screen_widgets` on them, add :ref:`basics_widgets` onto those Screens.
31To handle touch, mouse, keypad, etc., you :ref:`create an Input Device <indev_creation>`
32for each.  The :ref:`tick_interface` tells LVGL what time is it.  :ref:`timer_handler`
33drives LVGL's timers which, in turn, perform all of LVGL's time-related tasks:
34
35- periodically refreshes displays,
36- reads input devices,
37- fires events,
38- runs any animations, and
39- runs user-created timers.
40
41
42.. _applications_job:
43
44Application's Job
45-----------------
46
47After initialization, the application's job is merely to create Widget Trees when
48they are needed, manage events those Widgets generate (by way of user interaction
49and other things), and delete them when they are no longer needed.  LVGL takes care
50of the rest.
51
52
53
54.. _basics_major_concepts:
55
56Major Concepts
57**************
58
59
60.. _display-vs-screen:
61
62Display vs Screen
63-----------------
64Before we get into any details about Widgets, let us first clarify the difference
65between two terms that you will hereafter see frequently:
66
67- A **Display** or **Display Panel** is the physical hardware displaying the pixels.
68- A :ref:`display` object is an object in RAM that represents a **Display** meant
69  to be used by LVGL.
70- A **Screen** is the "root" Widget in the Widget Trees mentioned above, and are
71  "attached to" a particular :ref:`display`.
72
73
74Default Display
75---------------
76When the first :ref:`display` object is created, it becomes the Default Display.
77Many functions related to Screen Widgets use the default display.
78See :ref:`default_display` for more information.
79
80
81.. _basics_screen_widgets:
82
83Screen Widgets
84--------------
85In this documentation, the term "Screen Widget" is frequently shortened to just
86"Screen".  But it is important to understand that a "Screen" is simply any
87:ref:`Widget <widgets>` created without a parent --- the "root" of each Widget Tree.
88
89See :ref:`screens` for more details.
90
91
92Active Screen
93-------------
94
95The Active Screen is the screen (and its child Widgets) currently being displayed.
96See :ref:`active_screen` for more information.
97
98
99.. _basics_widgets:
100
101Widgets
102-------
103After LVGL is initialized (see :ref:`initializing_lvgl`), to create an interactive
104user interface, an application next creates a tree of Widgets that LVGL can render to
105the associated display, and with which the user can interact.
106
107Widgets are "intelligent" LVGL graphical elements such as :ref:`Base Widgets
108<base_widget_overview>` (simple rectangles and :ref:`screens`), Buttons, Labels,
109Checkboxes, Switches, Sliders, Charts, etc.  Go to :ref:`widgets` to see the full
110list.
111
112To build this Widget Tree, the application first acquires a pointer to a Screen Widget.
113A system designer is free to use the default Screen created with the :ref:`display`
114and/or create his own.  To create a new Screen Widget, simply create a Widget passing
115NULL as the parent argument.  Technically, this can be any type of Widget, but in
116most cases it is a :ref:`base_widget_overview`.  (An example of another type of
117Widget being used as a Screen is an :ref:`lv_image` Widget to supply an image for the
118background.)
119
120The application then adds Widgets to this Screen as children in the tree.  Widgets
121are automatically added as children to their parent Widgets at time of creation ---
122the Widget's parent is passed as the first argument to the function that creates
123the Widget.  After being so added, we say that the parent Widget "contains" the
124child Widget.
125
126Any Widget can contain other Widgets.  For example, if you want a Button to have
127text, create a Label Widget and add it to the Button as a child.
128
129Each child Widget becomes "part of" its parent Widget.  Because of this relationship:
130
131- when the parent Widget moves, its children move with it;
132- when the parent Widget is deleted, its children are deleted with it;
133- a child Widget is only visible within its parent's boundaries; any part of a child
134  outside its parent's boundaries is clipped (i.e. not rendered).
135
136Screens (and their child Widgets) can be created and deleted at any time *except*
137when the Screen is the :ref:`active_screen`.  If you want to delete the current Screen
138as you load a new one, call :cpp:func:`lv_screen_load_anim` and pass ``true`` for the
139``auto_del`` argument.  If you want to keep the current Screen in RAM when you load a
140new Screen, pass ``false`` for the ``auto_del`` argument, or call
141:cpp:func:`lv_screen_active` to load the new screen.
142
143A system designer is free to keep any number of Screens (and their child Widgets) in
144RAM (e.g. for quick re-display again later).  Doing so:
145
146- requires more RAM, but
147- can save the time of repeatedly creating the Screen and its child Widgets;
148- can be handy when a Screen is complex and/or can be made the :ref:`active_screen` frequently.
149
150If multiple Screens are maintained in RAM simultaneously, it is up to the system
151designer as to how they are managed.
152
153
154.. _basics_creating_widgets:
155
156Creating Widgets
157~~~~~~~~~~~~~~~~
158Widgets are created by calling functions that look like this::
159
160    lv_<type>_create(parent)
161
162The call will return an :cpp:type:`lv_obj_t` ``*`` pointer that can be used later to
163reference the Widget to set its attributes.
164
165For example:
166
167.. code-block:: c
168
169    lv_obj_t * slider1 = lv_slider_create(lv_screen_active());
170
171
172.. _basics_modifying_widgets:
173
174Modifying Widgets
175~~~~~~~~~~~~~~~~~
176Attributes common to all Widgets are set by functions that look like this::
177
178    lv_obj_set_<attribute_name>(widget, <value>)
179
180For example:
181
182.. code-block:: c
183
184    lv_obj_set_x(slider1, 30);
185    lv_obj_set_y(slider1, 10);
186    lv_obj_set_size(slider1, 200, 50);
187
188Along with these attributes, widgets can have type-specific attributes which are
189set by functions that look like this::
190
191    lv_<type>_set_<attribute_name>(widget, <value>)
192
193For example:
194
195.. code-block:: c
196
197    lv_slider_set_value(slider1, 70, LV_ANIM_ON);
198
199To see the full API visit the documentation of the Widget in question under
200:ref:`widgets` or study its related header file in the source code, e.g.
201
202- lvgl/src/widgets/slider/lv_slider.h
203
204or view it on GitHub, e.g.
205
206- https://github.com/lvgl/lvgl/blob/master/src/widgets/slider/lv_slider.h .
207
208
209.. _basics_deleting_widgets:
210
211Deleting Widgets
212~~~~~~~~~~~~~~~~
213To delete any widget and its children::
214
215    lv_obj_delete(lv_obj_t * widget)
216
217
218
219.. _basics_events:
220
221Events
222------
223
224Events are used to inform the application that something has happened with a Widget.
225You can assign one or more callbacks to a Widget which will be called when the
226Widget is clicked, released, dragged, being deleted, etc.
227
228A callback is assigned like this:
229
230.. code-block:: c
231
232   lv_obj_add_event_cb(btn, my_btn_event_cb, LV_EVENT_CLICKED, NULL);
233
234   ...
235
236   void my_btn_event_cb(lv_event_t * e)
237   {
238       printf("Clicked\n");
239   }
240
241:cpp:enumerator:`LV_EVENT_ALL` can be used instead of :cpp:enumerator:`LV_EVENT_CLICKED`
242to invoke the callback for all events.  (Beware:  there are a LOT of events!  This can
243be handy for debugging or learning what events occur for a given Widget, or indeed
244if the application needs to process all events for some reason.)
245
246Event callbacks receive the argument :cpp:expr:`lv_event_t * e` containing the
247current event code and other event-related information.  The current event code can
248be retrieved with:
249
250.. code-block:: c
251
252    lv_event_code_t code = lv_event_get_code(e);
253
254The Widget that triggered the event can be retrieved with:
255
256.. code-block:: c
257
258    lv_obj_t * obj = lv_event_get_target(e);
259
260To learn all features of the events go to the :ref:`events` section.
261
262
263.. _basics_parts:
264
265Parts
266-----
267
268Widgets are built from one or more *parts*.  For example, a button
269has only one part called :cpp:enumerator:`LV_PART_MAIN`. However, a
270:ref:`lv_slider` has :cpp:enumerator:`LV_PART_MAIN`, :cpp:enumerator:`LV_PART_INDICATOR`
271and :cpp:enumerator:`LV_PART_KNOB`.
272
273By using parts you can apply different styles to sub-elements of a widget.  (See below.)
274
275Read the Widget's documentation to learn which parts it uses.
276
277
278.. _basics_states:
279
280States
281------
282
283Widgets can be in a combination of the following states:
284
285- :cpp:enumerator:`LV_STATE_DEFAULT`: Normal, released state
286- :cpp:enumerator:`LV_STATE_CHECKED`: Toggled or checked state
287- :cpp:enumerator:`LV_STATE_FOCUSED`: Focused via keypad or encoder or clicked via touchpad/mouse
288- :cpp:enumerator:`LV_STATE_FOCUS_KEY`: Focused via keypad or encoder but not via touchpad/mouse
289- :cpp:enumerator:`LV_STATE_EDITED`: Edit by an encoder
290- :cpp:enumerator:`LV_STATE_HOVERED`: Hovered by mouse
291- :cpp:enumerator:`LV_STATE_PRESSED`: Being pressed
292- :cpp:enumerator:`LV_STATE_SCROLLED`: Being scrolled
293- :cpp:enumerator:`LV_STATE_DISABLED`: Disabled
294
295For example, if you press a Widget it will automatically go to the
296:cpp:enumerator:`LV_STATE_FOCUSED` and :cpp:enumerator:`LV_STATE_PRESSED` states and when you
297release it the :cpp:enumerator:`LV_STATE_PRESSED` state will be removed while the
298:cpp:enumerator:`LV_STATE_FOCUSED` state remains active.
299
300To check if a Widget is in a given state use
301:cpp:expr:`lv_obj_has_state(widget, LV_STATE_...)`. It will return ``true`` if the
302Widget is currently in that state.
303
304To manually add or remove states use:
305
306.. code-block:: c
307
308   lv_obj_add_state(widget, LV_STATE_...);
309   lv_obj_remove_state(widget, LV_STATE_...);
310
311
312.. _basics_styles:
313
314Styles
315------
316
317A style instance contains properties such as background color, border
318width, font, etc. that describe the appearance of Widgets.
319
320Styles are carried in :cpp:struct:`lv_style_t` objects.  Only their pointer is saved
321in the Widgets so they need to be defined as static or global variables.  Before
322using a style it needs to be initialized with :cpp:expr:`lv_style_init(&style1)`.
323After that, properties can be added to configure the style.  For example:
324
325.. code-block:: c
326
327    static lv_style_t style1;
328    lv_style_init(&style1);
329    lv_style_set_bg_color(&style1, lv_color_hex(0xa03080))
330    lv_style_set_border_width(&style1, 2))
331
332See :ref:`style_properties_overview` for more details.
333
334See :ref:`style_properties` to see the full list.
335
336Styles are assigned using the OR-ed combination of a Widget's part and
337state. For example to use this style on the slider's indicator when the
338slider is pressed:
339
340.. code-block:: c
341
342    lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR | LV_STATE_PRESSED);
343
344If the *part* is :cpp:enumerator:`LV_PART_MAIN` it can be omitted:
345
346.. code-block:: c
347
348    lv_obj_add_style(btn1, &style1, LV_STATE_PRESSED); /* Equal to LV_PART_MAIN | LV_STATE_PRESSED */
349
350Similarly, :cpp:enumerator:`LV_STATE_DEFAULT` can be omitted:
351
352.. code-block:: c
353
354   lv_obj_add_style(slider1, &style1, LV_PART_INDICATOR); /* Equal to LV_PART_INDICATOR | LV_STATE_DEFAULT */
355
356For :cpp:enumerator:`LV_STATE_DEFAULT` | :cpp:enumerator:`LV_PART_MAIN` simply pass ``0``:
357
358.. code-block:: c
359
360   lv_obj_add_style(btn1, &style1, 0); /* Equal to LV_PART_MAIN | LV_STATE_DEFAULT */
361
362Styles can be cascaded (similarly to CSS). This means you can add more
363styles to a part of a Widget. For example ``style_btn`` can set a
364default button appearance, and ``style_btn_red`` can overwrite the
365background color to make the button red:
366
367.. code-block:: c
368
369   lv_obj_add_style(btn1, &style_btn, 0);
370   lv_obj_add_style(btn1, &style1_btn_red, 0);
371
372If a property is not set for the current state, the style with
373:cpp:enumerator:`LV_STATE_DEFAULT` will be used. A default value is used if the
374property is not defined in the default state.
375
376Some properties (particularly the text-related ones) can be inherited. This
377means if a property is not set in a Widget it will be searched for in
378its parents. For example, you can set the font once in the screen's
379style and all text on that screen will inherit it by default.
380
381Local style properties also can be added to Widgets. This creates a
382style which resides inside the Widget and is used only by that Widget:
383
384.. code-block:: c
385
386    lv_obj_set_style_bg_color(slider1, lv_color_hex(0x2080bb), LV_PART_INDICATOR | LV_STATE_PRESSED);
387
388To learn all the features of styles see :ref:`styles`.
389
390
391.. _basics_themes:
392
393Themes
394------
395
396Themes are the default styles for Widgets. Styles from a theme are
397applied automatically when Widgets are created.
398
399The theme for your application is a compile time configuration set in
400``lv_conf.h``.
401
402
403.. _basics_micropython:
404
405MicroPython
406-----------
407
408LVGL can even be used with :ref:`micropython`.
409
410.. code-block:: python
411
412    # Initialize
413    import display_driver
414    import lvgl as lv
415
416    # Create a button with a label
417    scr = lv.obj()
418    btn = lv.button(scr)
419    btn.align(lv.ALIGN.CENTER, 0, 0)
420    label = lv.label(btn)
421    label.set_text('Hello World!')
422    lv.screen_load(scr)
423
424
425
426.. _going_deeper:
427
428Going Deeper
429*************
430
431There are several good ways ways to gain deeper knowledge of LVGL.  Here is one
432recommended order of documents to read and things to play with while you are
433advancing your knowledge:
434
4351. If not already read, start with :ref:`introduction` page of
436   the documentation.  (5 minutes)
4372. Check out the `Online Demos`_ to see LVGL in action.  (3 minutes)
4383. If not already done, read the :ref:`lvgl_basics` (above).  (15 minutes)
4394. Set up an LVGL :ref:`simulator`.  (10 minutes)
4405. Have a look at some :ref:`examples` and their code.
4416. Add LVGL to your project.  See :ref:`add_lvgl_to_your_project` or check out
442   the `ready-to-use Projects`_.
4437. Read the :ref:`main_components` pages to get a better understanding of the library. (2-3 hours)
4448. Skim the documentation of :ref:`widgets` to see what is available.
4459. If you have questions go to the `Forum`_.
44610. Read the :ref:`contributing` guide to see how you can help to improve LVGL. (15 minutes)
447
448
449.. _online demos:           https://lvgl.io/demos
450.. _ready-to-use projects:  https://github.com/lvgl?q=lv_port_&type=&language=
451.. _forum:                  https://forum.lvgl.io/
452
453
454
455.. _basics_examples:
456
457Basic Examples
458**************
459
460Below are several basic examples.  They include the application code that produces
461the Widget Tree needed to make LVGL render the examples shown.  Each example assumes
462a LVGL has undergone normal initialization, meaning that a ``lv_display_t`` object
463was created and therefore has an :ref:`active_screen`.
464
465
466.. include:: ../examples/get_started/index.rst
467
468
469