mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-27 20:57:01 +08:00
docs(intro): reorganize and simplify (#8389)
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Arduino Lint / lint (push) Has been cancelled
Build Examples with C++ Compiler / build-examples (push) Has been cancelled
MicroPython CI / Build esp32 port (push) Has been cancelled
MicroPython CI / Build rp2 port (push) Has been cancelled
MicroPython CI / Build stm32 port (push) Has been cancelled
MicroPython CI / Build unix port (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_NORMAL_8BIT - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_SDL - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - Ubuntu (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_16BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_24BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_FULL_32BIT - gcc - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - cl - Windows (push) Has been cancelled
C/C++ CI / Build OPTIONS_VG_LITE - gcc - Windows (push) Has been cancelled
C/C++ CI / Build ESP IDF ESP32S3 (push) Has been cancelled
C/C++ CI / Run tests with 32bit build (push) Has been cancelled
C/C++ CI / Run tests with 64bit build (push) Has been cancelled
BOM Check / bom-check (push) Has been cancelled
Verify that lv_conf_internal.h matches repository state / verify-conf-internal (push) Has been cancelled
Verify the widget property name / verify-property-name (push) Has been cancelled
Verify code formatting / verify-formatting (push) Has been cancelled
Compare file templates with file names / template-check (push) Has been cancelled
Build docs / build-and-deploy (push) Has been cancelled
Test API JSON generator / Test API JSON (push) Has been cancelled
Check Makefile / Build using Makefile (push) Has been cancelled
Check Makefile for UEFI / Build using Makefile for UEFI (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_32B - Ubuntu (push) Has been cancelled
Performance Tests CI / Perf Tests OPTIONS_TEST_PERF_64B - Ubuntu (push) Has been cancelled
Port repo release update / run-release-branch-updater (push) Has been cancelled
Verify Font License / verify-font-license (push) Has been cancelled
Verify Kconfig / verify-kconfig (push) Has been cancelled
Close stale issues and PRs / stale (push) Has been cancelled
Co-authored-by: Victor Wheeler <vwheeler63@users.noreply.github.com> Co-authored-by: Liam Howatt <30486941+liamHowatt@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
63b1dcecc8
commit
4668ed768f
+2
-2
@@ -61,8 +61,8 @@ Introduction
|
|||||||
:class: toctree-1-deep toctree-landing-page
|
:class: toctree-1-deep toctree-landing-page
|
||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
intro/introduction
|
intro/introduction/index
|
||||||
intro/getting_started
|
intro/getting_started/index
|
||||||
|
|
||||||
|
|
||||||
Details
|
Details
|
||||||
|
|||||||
@@ -1,447 +0,0 @@
|
|||||||
.. _getting_started:
|
|
||||||
|
|
||||||
===============
|
|
||||||
Getting Started
|
|
||||||
===============
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _lvgl_basics:
|
|
||||||
|
|
||||||
LVGL Basics
|
|
||||||
***********
|
|
||||||
|
|
||||||
LVGL (Light and Versatile Graphics Library) is a free and open-source graphics
|
|
||||||
library providing everything you need to create an embedded GUI with easy-to-use
|
|
||||||
mobile-phone-like graphical elements, beautiful visual effects, and a low memory
|
|
||||||
footprint.
|
|
||||||
|
|
||||||
How does it do this?
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _basic_data_flow:
|
|
||||||
|
|
||||||
Overview of LVGL's Data Flow
|
|
||||||
****************************
|
|
||||||
|
|
||||||
.. figure:: /_static/images/intro_data_flow.png
|
|
||||||
:scale: 75 %
|
|
||||||
:alt: LVGL Data Flow
|
|
||||||
:align: center
|
|
||||||
:figwidth: image
|
|
||||||
|
|
||||||
Overview of LVGL Data Flow
|
|
||||||
|
|
||||||
You :ref:`add LVGL to your project <adding_lvgl_to_your_project>`, provide it with
|
|
||||||
inputs and the method for pixels to flow to the display panel(s), connect the
|
|
||||||
:ref:`tick_interface` so LVGL can tell what time is it, periodically call
|
|
||||||
:ref:`timer_handler`, build one or more :ref:`Widget Trees <widget_overview>` for
|
|
||||||
LVGL to render the interactive UI, and let LVGL do the rest.
|
|
||||||
|
|
||||||
The :ref:`timer_handler` function drives LVGL's timers which, in turn, perform a
|
|
||||||
number of periodic tasks:
|
|
||||||
|
|
||||||
- refresh display(s),
|
|
||||||
- read input devices,
|
|
||||||
- fire events based on user input (and other things),
|
|
||||||
- run any animations, and
|
|
||||||
- run user-created timers.
|
|
||||||
|
|
||||||
|
|
||||||
.. _applications_job:
|
|
||||||
|
|
||||||
Application's Job
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
After initialization, the application's job is merely to create :ref:`Widget Trees
|
|
||||||
<widget_overview>` when they are needed, manage events those Widgets generate
|
|
||||||
(through user interactions and similar), and delete them when they are no
|
|
||||||
longer needed. LVGL takes care of the rest.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_major_concepts:
|
|
||||||
|
|
||||||
Major Concepts
|
|
||||||
**************
|
|
||||||
|
|
||||||
|
|
||||||
.. _display-vs-screen:
|
|
||||||
|
|
||||||
Display vs Screen
|
|
||||||
-----------------
|
|
||||||
Before we get into any details about Widgets, let us first clarify the difference
|
|
||||||
between two terms that you will hereafter see frequently:
|
|
||||||
|
|
||||||
- A **Display** or **Display Panel** is the physical hardware displaying the pixels.
|
|
||||||
- A :ref:`display` object is an object in RAM that represents a **Display** LVGL will render to.
|
|
||||||
- **Screen** objects are the "root" Widgets in the :ref:`Widget Trees <widget_overview>`
|
|
||||||
mentioned above, and each **Screen** is "attached to" a particular :ref:`display`.
|
|
||||||
|
|
||||||
|
|
||||||
Default Display
|
|
||||||
---------------
|
|
||||||
When the first :ref:`display` object is created, it becomes the Default Display.
|
|
||||||
Many functions related to Screen Widgets use the default display.
|
|
||||||
See :ref:`default_display` for more information.
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_screen_widgets:
|
|
||||||
|
|
||||||
Screen Widgets
|
|
||||||
--------------
|
|
||||||
In this documentation, the term "Screen Widget" is frequently shortened to just
|
|
||||||
"Screen". A "Screen" is simply any :ref:`Widget <widgets>` created without a parent
|
|
||||||
--- the "root" of each Widget Tree.
|
|
||||||
|
|
||||||
See :ref:`screens` for more details.
|
|
||||||
|
|
||||||
|
|
||||||
Active Screen
|
|
||||||
-------------
|
|
||||||
|
|
||||||
The Active Screen is the screen (and its child Widgets) currently being displayed.
|
|
||||||
See :ref:`active_screen` for more information.
|
|
||||||
|
|
||||||
|
|
||||||
.. _widget_overview:
|
|
||||||
|
|
||||||
Widgets
|
|
||||||
-------
|
|
||||||
After LVGL is initialized (see :ref:`initializing_lvgl`), an application creates a
|
|
||||||
tree of Widgets that LVGL can render to the associated display to create a user
|
|
||||||
interface with which the user can interact.
|
|
||||||
|
|
||||||
Widgets are "intelligent" LVGL graphical elements such as :ref:`Base Widget
|
|
||||||
<base_widget>` (simple rectangles and :ref:`screens`), Buttons, Labels, Checkboxes,
|
|
||||||
Switches, Sliders, Charts, etc. See :ref:`widgets` to see the full list.
|
|
||||||
|
|
||||||
To build this Widget Tree, the application first acquires a pointer to a Screen Widget.
|
|
||||||
You are free to use the default Screen created with the :ref:`display` and/or
|
|
||||||
create your own. To create a new Screen Widget, simply create a Widget with
|
|
||||||
NULL as the parent argument. Technically, this can be any type of Widget, but in
|
|
||||||
most cases it is a :ref:`base_widget`. (An example of another type of Widget
|
|
||||||
sometimes used as a Screen is an :ref:`lv_image` Widget to supply an image for the
|
|
||||||
background.)
|
|
||||||
|
|
||||||
The application then adds Widgets to this Screen which are children in its tree.
|
|
||||||
Widgets are automatically added as children to their parent Widgets at time of creation ---
|
|
||||||
the Widget's parent is passed as the first argument to the function that creates
|
|
||||||
the Widget. After being added, we say that the parent Widget "contains" the
|
|
||||||
child Widget.
|
|
||||||
|
|
||||||
Any Widget can contain other Widgets. For example, if you want a Button to have
|
|
||||||
text, create a Label Widget and add it to the Button as a child.
|
|
||||||
|
|
||||||
Each child Widget becomes "part of" its parent Widget. Because of this relationship:
|
|
||||||
|
|
||||||
- when the parent Widget moves, its children move with it;
|
|
||||||
- when the parent Widget is deleted, its children are deleted with it;
|
|
||||||
- a child Widget is only visible within its parent's boundaries; any part of a child
|
|
||||||
outside its parent's boundaries is clipped (i.e. not rendered).
|
|
||||||
|
|
||||||
Screens (and their child Widgets) can be created and deleted at any time *except*
|
|
||||||
when the Screen is the :ref:`active_screen`. If you want to delete the current Screen
|
|
||||||
as you load a new one, call :cpp:func:`lv_screen_load_anim` and pass ``true`` for the
|
|
||||||
``auto_del`` argument. If you want to keep the current Screen in RAM when you load a
|
|
||||||
new Screen, pass ``false`` instead, or call :cpp:func:`lv_screen_load` to load the
|
|
||||||
new screen.
|
|
||||||
|
|
||||||
You are free to keep any number of Screens (and their child Widgets) in
|
|
||||||
RAM (e.g. for quick re-display again later). Doing so:
|
|
||||||
|
|
||||||
- requires more RAM,
|
|
||||||
- avoids repeatedly creating the Screen and its child Widgets, and
|
|
||||||
- can be handy when a Screen is complex and/or can be made the :ref:`active_screen` frequently.
|
|
||||||
|
|
||||||
If multiple Screens are maintained in RAM simultaneously, it is up to you how they
|
|
||||||
are managed.
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_creating_widgets:
|
|
||||||
|
|
||||||
Creating Widgets
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
Widgets are created by calling functions that look like this::
|
|
||||||
|
|
||||||
lv_<type>_create(parent)
|
|
||||||
|
|
||||||
The call will return an :cpp:expr:`lv_obj_t *` pointer that can be used later to
|
|
||||||
reference the Widget to set its attributes.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_obj_t * slider1 = lv_slider_create(lv_screen_active());
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_modifying_widgets:
|
|
||||||
|
|
||||||
Modifying Widgets
|
|
||||||
~~~~~~~~~~~~~~~~~
|
|
||||||
Attributes common to all Widgets are set by functions that look like this::
|
|
||||||
|
|
||||||
lv_obj_set_<attribute_name>(widget, <value>)
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_obj_set_x(slider1, 30);
|
|
||||||
lv_obj_set_y(slider1, 10);
|
|
||||||
lv_obj_set_size(slider1, 200, 50);
|
|
||||||
|
|
||||||
All such functions are covered in :ref:`common_widget_features`.
|
|
||||||
|
|
||||||
Along with these attributes, widgets can have type-specific attributes which are
|
|
||||||
set by functions that look like this::
|
|
||||||
|
|
||||||
lv_<type>_set_<attribute_name>(widget, <value>)
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_slider_set_value(slider1, 70, LV_ANIM_ON);
|
|
||||||
|
|
||||||
To see the full API for any Widget, see its documentation at :ref:`widgets`, study
|
|
||||||
its related header file in the source code, e.g.
|
|
||||||
|
|
||||||
- lvgl/src/widgets/slider/lv_slider.h
|
|
||||||
|
|
||||||
or view it on GitHub, e.g.
|
|
||||||
|
|
||||||
- https://github.com/lvgl/lvgl/blob/master/src/widgets/slider/lv_slider.h .
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_deleting_widgets:
|
|
||||||
|
|
||||||
Deleting Widgets
|
|
||||||
~~~~~~~~~~~~~~~~
|
|
||||||
To delete any widget and its children::
|
|
||||||
|
|
||||||
lv_obj_delete(lv_obj_t * widget)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_events:
|
|
||||||
|
|
||||||
Events
|
|
||||||
------
|
|
||||||
|
|
||||||
Events are used to inform the application that something has happened with a Widget.
|
|
||||||
You can assign one or more callbacks to a Widget which will be called when the Widget
|
|
||||||
is clicked, released, dragged, being deleted, etc.
|
|
||||||
|
|
||||||
A callback is assigned like this:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_obj_add_event_cb(btn, my_btn_event_cb, LV_EVENT_CLICKED, NULL);
|
|
||||||
|
|
||||||
...
|
|
||||||
|
|
||||||
void my_btn_event_cb(lv_event_t * e)
|
|
||||||
{
|
|
||||||
printf("Clicked\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
:cpp:enumerator:`LV_EVENT_ALL` can be used instead of :cpp:enumerator:`LV_EVENT_CLICKED`
|
|
||||||
to invoke the callback for all events. (Beware: there are a LOT of events! This can
|
|
||||||
be handy for debugging or learning what events occur for a given Widget or if, for
|
|
||||||
some reason, the application needs to process all events.)
|
|
||||||
|
|
||||||
Event callbacks receive the argument :cpp:expr:`lv_event_t * e` containing the
|
|
||||||
current event code and other event-related information. The current event code can
|
|
||||||
be retrieved with:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_event_code_t code = lv_event_get_code(e);
|
|
||||||
|
|
||||||
The Widget that triggered the event can be retrieved with:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_obj_t * widget = lv_event_get_target(e);
|
|
||||||
|
|
||||||
Learn all about Events in the :ref:`events` section.
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_parts:
|
|
||||||
|
|
||||||
Parts
|
|
||||||
-----
|
|
||||||
|
|
||||||
Widgets are built from one or more *parts*. For example, a button
|
|
||||||
has only one part called :cpp:enumerator:`LV_PART_MAIN`. However, a
|
|
||||||
:ref:`lv_slider` has :cpp:enumerator:`LV_PART_MAIN`, :cpp:enumerator:`LV_PART_INDICATOR`
|
|
||||||
and :cpp:enumerator:`LV_PART_KNOB`.
|
|
||||||
|
|
||||||
By using parts you can apply different :ref:`styles <basics_styles>` to sub-elements
|
|
||||||
of a widget.
|
|
||||||
|
|
||||||
Read the Widget's documentation to learn which parts it uses.
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_states:
|
|
||||||
|
|
||||||
States
|
|
||||||
------
|
|
||||||
|
|
||||||
Widgets can be in a combination of the following states:
|
|
||||||
|
|
||||||
- :cpp:enumerator:`LV_STATE_DEFAULT`: Normal, released state
|
|
||||||
- :cpp:enumerator:`LV_STATE_CHECKED`: Toggled or checked state
|
|
||||||
- :cpp:enumerator:`LV_STATE_FOCUSED`: Focused via keypad or encoder or clicked via touchpad/mouse
|
|
||||||
- :cpp:enumerator:`LV_STATE_FOCUS_KEY`: Focused via keypad or encoder but not via touchpad/mouse
|
|
||||||
- :cpp:enumerator:`LV_STATE_EDITED`: Edited by an encoder
|
|
||||||
- :cpp:enumerator:`LV_STATE_HOVERED`: Hovered by mouse
|
|
||||||
- :cpp:enumerator:`LV_STATE_PRESSED`: Being pressed
|
|
||||||
- :cpp:enumerator:`LV_STATE_SCROLLED`: Being scrolled
|
|
||||||
- :cpp:enumerator:`LV_STATE_DISABLED`: Disabled
|
|
||||||
|
|
||||||
For example, if you press a Widget it will automatically go to the
|
|
||||||
:cpp:enumerator:`LV_STATE_FOCUSED` and :cpp:enumerator:`LV_STATE_PRESSED` states. When you
|
|
||||||
release it the :cpp:enumerator:`LV_STATE_PRESSED` state will be removed while the
|
|
||||||
:cpp:enumerator:`LV_STATE_FOCUSED` state remains active.
|
|
||||||
|
|
||||||
To check if a Widget is in a given state use
|
|
||||||
:cpp:expr:`lv_obj_has_state(widget, LV_STATE_...)`. It will return ``true`` if the
|
|
||||||
Widget is currently in that state.
|
|
||||||
|
|
||||||
To programmatically add or remove states use:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_obj_add_state(widget, LV_STATE_...);
|
|
||||||
lv_obj_remove_state(widget, LV_STATE_...);
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_styles:
|
|
||||||
|
|
||||||
Styles
|
|
||||||
------
|
|
||||||
|
|
||||||
A style instance contains properties such as background color, border
|
|
||||||
width, font, etc. that describe the appearance of Widgets.
|
|
||||||
|
|
||||||
Styles are carried in :cpp:struct:`lv_style_t` objects. Only their pointer is saved
|
|
||||||
in the Widgets so they need to be defined as static or global variables. Before
|
|
||||||
using a style it needs to be initialized with ``lv_style_init(&style1)``.
|
|
||||||
After that, properties can be added to configure the style. For example:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
static lv_style_t style1;
|
|
||||||
lv_style_init(&style1);
|
|
||||||
lv_style_set_bg_color(&style1, lv_color_hex(0xa03080))
|
|
||||||
lv_style_set_border_width(&style1, 2))
|
|
||||||
|
|
||||||
See :ref:`style_properties_overview` for more details.
|
|
||||||
|
|
||||||
See :ref:`style_properties` to see the full list.
|
|
||||||
|
|
||||||
If a property is not set for the current state, the style with
|
|
||||||
:cpp:enumerator:`LV_STATE_DEFAULT` will be used. A default value is used if the
|
|
||||||
property is not defined in the default state.
|
|
||||||
|
|
||||||
Some properties (particularly the text-related ones) can be inherited. This
|
|
||||||
means if a property is not set in a Widget it will be searched for in
|
|
||||||
its parents. For example, you can set the font once in the screen's
|
|
||||||
style and all text on that screen will inherit it by default.
|
|
||||||
|
|
||||||
Local style properties also can be added to Widgets. This creates a
|
|
||||||
style which resides inside the Widget and is used only by that Widget:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
lv_obj_set_style_bg_color(slider1, lv_color_hex(0x2080bb), LV_PART_INDICATOR | LV_STATE_PRESSED);
|
|
||||||
|
|
||||||
See :ref:`styles` for full details.
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_themes:
|
|
||||||
|
|
||||||
Themes
|
|
||||||
------
|
|
||||||
|
|
||||||
Themes are a set of default styles for Widgets. Styles from an active theme are
|
|
||||||
applied automatically when Widgets are created.
|
|
||||||
|
|
||||||
The theme for your application is a compile time configuration setting in
|
|
||||||
``lv_conf.h``.
|
|
||||||
|
|
||||||
|
|
||||||
.. _basics_micropython:
|
|
||||||
|
|
||||||
MicroPython
|
|
||||||
-----------
|
|
||||||
|
|
||||||
LVGL can even be used with :ref:`micropython`.
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# Initialize
|
|
||||||
import display_driver
|
|
||||||
import lvgl as lv
|
|
||||||
|
|
||||||
# Create a button with a label
|
|
||||||
scr = lv.obj()
|
|
||||||
btn = lv.button(scr)
|
|
||||||
btn.align(lv.ALIGN.CENTER, 0, 0)
|
|
||||||
label = lv.label(btn)
|
|
||||||
label.set_text('Hello World!')
|
|
||||||
lv.screen_load(scr)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _basic_examples:
|
|
||||||
|
|
||||||
Basic Examples
|
|
||||||
**************
|
|
||||||
|
|
||||||
Below are several basic examples. They include the application code that produces
|
|
||||||
the Widget Tree needed to make LVGL render the examples shown. Each example assumes
|
|
||||||
a LVGL has undergone normal initialization, meaning that a ``lv_display_t`` object
|
|
||||||
was created and therefore has an :ref:`active_screen`.
|
|
||||||
|
|
||||||
.. include:: ../examples/get_started/index.rst
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _whats_next:
|
|
||||||
|
|
||||||
What's Next?
|
|
||||||
************
|
|
||||||
|
|
||||||
There are several good ways ways to gain deeper knowledge of LVGL. Here is one
|
|
||||||
recommended order of documents to read and things to play with while you are
|
|
||||||
advancing your knowledge:
|
|
||||||
|
|
||||||
1. If not already read, start with :ref:`introduction` page of
|
|
||||||
the documentation. (5 minutes)
|
|
||||||
2. Check out the `Online Demos`_ to see LVGL in action. (3 minutes)
|
|
||||||
3. If not already done, read the :ref:`lvgl_basics` (above). (15 minutes)
|
|
||||||
4. Set up an LVGL :ref:`simulator`. (10 minutes)
|
|
||||||
5. Have a look at some :ref:`examples` and their code.
|
|
||||||
6. :ref:`Add LVGL to your project <adding_lvgl_to_your_project>` or check out
|
|
||||||
the `ready-to-use Projects`_.
|
|
||||||
7. Read the :ref:`main_modules` pages to get a better understanding of the library. (2-3 hours)
|
|
||||||
8. Skim the documentation of :ref:`widgets` to see what is available.
|
|
||||||
9. If you have questions go to the `Forum`_.
|
|
||||||
10. Read the :ref:`contributing` guide to see how you can help to improve LVGL. (15 minutes)
|
|
||||||
|
|
||||||
|
|
||||||
.. _online demos: https://lvgl.io/demos
|
|
||||||
.. _ready-to-use projects: https://github.com/lvgl?q=lv_port_&type=&language=
|
|
||||||
.. _forum: https://forum.lvgl.io/
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
API
|
|
||||||
***
|
|
||||||
.. API equals: lv_screen_load, lv_obj_delete, lv_obj_add_event_cb, lv_event_get_code,
|
|
||||||
lv_obj_has_state, lv_style_init
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
|
||||||
|
==============
|
||||||
|
Basic Examples
|
||||||
|
==============
|
||||||
|
|
||||||
|
Below are several basic examples. They include the application code that produces
|
||||||
|
the Widget Tree needed to make LVGL render the examples shown. Each example assumes
|
||||||
|
LVGL has undergone normal initialization, meaning that a ``lv_display_t`` object
|
||||||
|
was created and therefore has an :ref:`active_screen`.
|
||||||
|
|
||||||
|
.. include:: ../../examples/get_started/index.rst
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
.. _getting_started:
|
||||||
|
|
||||||
|
===============
|
||||||
|
Getting started
|
||||||
|
===============
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
learn_the_basics
|
||||||
|
examples
|
||||||
|
whats_next
|
||||||
@@ -0,0 +1,376 @@
|
|||||||
|
.. _learn_the_basics:
|
||||||
|
|
||||||
|
================
|
||||||
|
Learn the Basics
|
||||||
|
================
|
||||||
|
|
||||||
|
Overview
|
||||||
|
********
|
||||||
|
|
||||||
|
LVGL (Light and Versatile Graphics Library) is a free and open-source graphics
|
||||||
|
library providing everything you need to create an embedded GUI with easy-to-use
|
||||||
|
mobile-phone-like graphical elements, beautiful visual effects, and a low memory
|
||||||
|
footprint.
|
||||||
|
|
||||||
|
You can think of LVGL as a collection of C and H files that can be dropped into
|
||||||
|
any project to add UI capabilities to the product.
|
||||||
|
|
||||||
|
With the help of consistent and easy-to-learn API functions you can create widgets
|
||||||
|
(buttons, sliders, charts, etc), style them, add events, layouts, or animations.
|
||||||
|
|
||||||
|
Based on these settings LVGL will render an image (either by using its built-in
|
||||||
|
software rendering engine or a GPU) and will call a callback function to show
|
||||||
|
the rendered image on the display. This callback function is the main interface
|
||||||
|
between LVGL and the display. Most of the porting-related work is focused on
|
||||||
|
writing such a callback in an effective way.
|
||||||
|
|
||||||
|
This chapter will show the basics to give an idea about how LVGL works and how it can be used.
|
||||||
|
For more details about each feature visit that feature's dedicated documentation page.
|
||||||
|
|
||||||
|
.. _basic_data_flow:
|
||||||
|
|
||||||
|
Basic Data Flow
|
||||||
|
---------------
|
||||||
|
|
||||||
|
1. **Driver Initialization**: It's the user's responsibility to set up the clock, timers, peripherals, etc.
|
||||||
|
2. **Call lv_init()**: It initializes LVGL itself
|
||||||
|
3. **Create display and input devices**: Create display(s) (:cpp:type:`lv_display_t`) and input device(s) (:cpp:type:`lv_indev_t`) and set up their callbacks
|
||||||
|
4. **Create the UI**: Call LVGL functions to create screens, widgets, styles, animations, events, etc.
|
||||||
|
5. **Call lv_timer_handler() in a loop**: It handles all the LVGL-related tasks:
|
||||||
|
- refresh display(s),
|
||||||
|
- read input devices,
|
||||||
|
- fire events based on user input (and other things),
|
||||||
|
- run any animations, and
|
||||||
|
- run user-created timers.
|
||||||
|
|
||||||
|
Integration example
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
This is just a brief example of how to add LVGL to a new project. For more details
|
||||||
|
check out :ref:`adding_lvgl_to_your_project`.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
void main(void)
|
||||||
|
{
|
||||||
|
your_driver_init();
|
||||||
|
|
||||||
|
lv_init();
|
||||||
|
|
||||||
|
lv_tick_set_cb(my_get_millis);
|
||||||
|
|
||||||
|
lv_display_t * display = lv_display_create(320, 240);
|
||||||
|
|
||||||
|
/*LVGL will render to this 1/10 screen sized buffer for 2 bytes/pixel*/
|
||||||
|
static uint8_t buf[320 * 240 / 10 * 2];
|
||||||
|
lv_display_set_buffers(display, buf, NULL, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||||
|
|
||||||
|
/*This callback will display the rendered image*/
|
||||||
|
lv_display_set_flush_cb(display, my_flush_cb);
|
||||||
|
|
||||||
|
/*Create widgets*/
|
||||||
|
lv_obj_t * label = lv_label_create(lv_screen_active());
|
||||||
|
lv_label_set_text(label, "Hello LVGL!");
|
||||||
|
|
||||||
|
/*Make LVGL periodically execute its tasks*/
|
||||||
|
while(1) {
|
||||||
|
lv_timer_handler();
|
||||||
|
my_sleep(5); /*Wait 5 milliseconds before processing LVGL timer again*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Return the elapsed milliseconds since startup.
|
||||||
|
*It needs to be implemented by the user*/
|
||||||
|
uint32_t my_get_millis(void)
|
||||||
|
{
|
||||||
|
return my_tick_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Copy the rendered image to the screen.
|
||||||
|
*It needs to be implemented by the user*/
|
||||||
|
void my_flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_buf)
|
||||||
|
{
|
||||||
|
/*Show the rendered image on the display*/
|
||||||
|
my_display_update(area, px_buf);
|
||||||
|
|
||||||
|
/*Indicate that the buffer is available.
|
||||||
|
*If DMA were used, call in the DMA complete interrupt*/
|
||||||
|
lv_display_flush_ready();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.. _basics_displays:
|
||||||
|
|
||||||
|
Displays
|
||||||
|
********
|
||||||
|
|
||||||
|
*Display* refers to the actual hardware. In order to connect LVGL to the hardware an :cpp:expr:`lv_display_t`
|
||||||
|
object needs to be created and initialized.
|
||||||
|
|
||||||
|
LVGL has built-in support for many :ref:`built-in drivers <drivers>`, but it's easy to initialize a
|
||||||
|
display from scratch as well (as shown above).
|
||||||
|
|
||||||
|
LVGL also handles multiple displays at once.
|
||||||
|
|
||||||
|
.. _basics_screens:
|
||||||
|
|
||||||
|
Screens
|
||||||
|
*******
|
||||||
|
|
||||||
|
A *Screen* is an LVGL widget created on a *Display*. It's a logical container for other widgets. A display can
|
||||||
|
have multiple screens, but there is always one active screen, which can be retrieved by using :cpp:expr:`lv_screen_active()`.
|
||||||
|
It returns an `lv_obj_t *` pointer. See :ref:`active_screen` for more information.
|
||||||
|
|
||||||
|
The most common way to create a screen is by creating a :ref:`Base widget <base_widget>` with a ``NULL`` parent. E.g.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_t * my_screen = lv_obj_create(NULL);
|
||||||
|
|
||||||
|
A screen can be loaded like this: :cpp:expr:`lv_screen_load(my_screen)`
|
||||||
|
|
||||||
|
.. _basics:widgets:
|
||||||
|
|
||||||
|
Widgets
|
||||||
|
*******
|
||||||
|
|
||||||
|
Widgets are the basic building blocks of the UI. For example:
|
||||||
|
:ref:`lv_button`, :ref:`lv_slider`, :ref:`lv_dropdown`, :ref:`lv_chart`, etc.
|
||||||
|
|
||||||
|
Widgets can be created dynamically by calling their respective create functions. The
|
||||||
|
create function returns an ``lv_obj_t *`` pointer which can be used to configure the widget later.
|
||||||
|
|
||||||
|
Each create function has a single ``parent`` argument that defines which widget the new one will be added to.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_t * my_button1 = lv_button_create(lv_screen_active());
|
||||||
|
lv_obj_t * my_label1 = lv_label_create(my_button1);
|
||||||
|
|
||||||
|
If a widget or screen is no longer needed, it can be removed by calling
|
||||||
|
:cpp:expr:`lv_obj_delete(my_button1)`
|
||||||
|
|
||||||
|
To change the properties of widgets, two sets of functions can be used:
|
||||||
|
|
||||||
|
- ``lv_obj_...()`` functions for common properties, e.g. :cpp:expr:`lv_obj_set_width()`, :cpp:expr:`lv_obj_add_style()`, etc. These are covered in :ref:`common_widget_features`.
|
||||||
|
|
||||||
|
- ``lv_<widget_type>_...()`` functions for type-specific properties, e.g. :cpp:expr:`lv_label_set_text()`, :cpp:expr:`lv_slider_set_value()`, etc.
|
||||||
|
|
||||||
|
Here is an example that also shows some non-pixel units for sizes:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_t * my_button1 = lv_button_create(lv_screen_active());
|
||||||
|
/*Set parent-sized width, and content-sized height*/
|
||||||
|
lv_obj_set_size(my_button1, lv_pct(100), LV_SIZE_CONTENT);
|
||||||
|
/*Align to the right center with 20px offset horizontally*/
|
||||||
|
lv_obj_align(my_button1, LV_ALIGN_RIGHT_MID, -20, 0);
|
||||||
|
|
||||||
|
lv_obj_t * my_label1 = lv_label_create(my_button1);
|
||||||
|
lv_label_set_text_fmt(my_label1, "Click me!");
|
||||||
|
lv_obj_set_style_text_color(my_label1, lv_color_hex(0xff0000), 0);
|
||||||
|
/*Make the text red*/
|
||||||
|
|
||||||
|
To see the full API for any widget, see its documentation at :ref:`widgets`, or check
|
||||||
|
its related header file in the source code.
|
||||||
|
|
||||||
|
|
||||||
|
.. _basics_events:
|
||||||
|
|
||||||
|
Events
|
||||||
|
******
|
||||||
|
|
||||||
|
Events are used to inform the application that something has happened with a Widget.
|
||||||
|
You can assign one or more callbacks to a Widget which will be called when the Widget
|
||||||
|
is clicked, released, dragged, being deleted, etc.
|
||||||
|
|
||||||
|
A callback is assigned like this:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_add_event_cb(btn, my_btn_event_cb, LV_EVENT_CLICKED, NULL);
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
void my_btn_event_cb(lv_event_t * e)
|
||||||
|
{
|
||||||
|
printf("Clicked\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
:cpp:enumerator:`LV_EVENT_ALL` can be used instead of :cpp:enumerator:`LV_EVENT_CLICKED`
|
||||||
|
to invoke the callback for all events.
|
||||||
|
|
||||||
|
Event callbacks receive the argument :cpp:expr:`lv_event_t * e` containing the
|
||||||
|
current event code and other event-related information. The current event code can
|
||||||
|
be retrieved with:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_event_code_t code = lv_event_get_code(e);
|
||||||
|
|
||||||
|
The Widget that triggered the event can be retrieved with:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_t * widget = lv_event_get_target_obj(e);
|
||||||
|
|
||||||
|
Learn all about Events in the :ref:`events` section.
|
||||||
|
|
||||||
|
Parts and States
|
||||||
|
****************
|
||||||
|
|
||||||
|
.. _basics_parts:
|
||||||
|
|
||||||
|
Parts
|
||||||
|
-----
|
||||||
|
|
||||||
|
Widgets are built from one or more *parts*. For example, a button
|
||||||
|
has only one part called :cpp:enumerator:`LV_PART_MAIN`. However, a
|
||||||
|
:ref:`lv_slider` has :cpp:enumerator:`LV_PART_MAIN`, :cpp:enumerator:`LV_PART_INDICATOR`
|
||||||
|
and :cpp:enumerator:`LV_PART_KNOB`.
|
||||||
|
|
||||||
|
By using parts you can apply different :ref:`styles <basics_styles>` to the parts
|
||||||
|
of a widget.
|
||||||
|
|
||||||
|
Read the Widget's documentation to learn which parts it uses.
|
||||||
|
|
||||||
|
.. _basics_states:
|
||||||
|
|
||||||
|
States
|
||||||
|
------
|
||||||
|
|
||||||
|
Widgets can be in a combination of the following states:
|
||||||
|
|
||||||
|
- :cpp:enumerator:`LV_STATE_DEFAULT`: Normal, released state
|
||||||
|
- :cpp:enumerator:`LV_STATE_CHECKED`: Toggled or checked state
|
||||||
|
- :cpp:enumerator:`LV_STATE_FOCUSED`: Focused via keypad or encoder or clicked via touchpad/mouse
|
||||||
|
- :cpp:enumerator:`LV_STATE_FOCUS_KEY`: Focused via keypad or encoder but not via touchpad/mouse
|
||||||
|
- :cpp:enumerator:`LV_STATE_EDITED`: Edited by an encoder
|
||||||
|
- :cpp:enumerator:`LV_STATE_HOVERED`: Hovered by mouse
|
||||||
|
- :cpp:enumerator:`LV_STATE_PRESSED`: Being pressed
|
||||||
|
- :cpp:enumerator:`LV_STATE_SCROLLED`: Being scrolled
|
||||||
|
- :cpp:enumerator:`LV_STATE_DISABLED`: Disabled
|
||||||
|
|
||||||
|
For example, if you press a Widget it will automatically go to the
|
||||||
|
:cpp:enumerator:`LV_STATE_FOCUSED` and :cpp:enumerator:`LV_STATE_PRESSED` states. When you
|
||||||
|
release it, the :cpp:enumerator:`LV_STATE_PRESSED` state will be removed while the
|
||||||
|
:cpp:enumerator:`LV_STATE_FOCUSED` state remains active.
|
||||||
|
|
||||||
|
To check if a Widget is in a given state use
|
||||||
|
:cpp:expr:`lv_obj_has_state(widget, LV_STATE_...)`. It will return ``true`` if the
|
||||||
|
Widget is currently in that state.
|
||||||
|
|
||||||
|
To programmatically add or remove states use:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_add_state(widget, LV_STATE_...);
|
||||||
|
lv_obj_remove_state(widget, LV_STATE_...);
|
||||||
|
|
||||||
|
.. _basics_styles:
|
||||||
|
|
||||||
|
Styles
|
||||||
|
******
|
||||||
|
|
||||||
|
Initializing styles
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
Styles are carried in :cpp:struct:`lv_style_t` objects. They contain properties such as
|
||||||
|
background color, border width, font, etc.
|
||||||
|
|
||||||
|
The styles can be added to a widget's given :ref:`Part <basics_parts>` and :ref:`State <basics_states>`.
|
||||||
|
Only their pointer is saved in the Widgets so they need to be defined as static or global variables.
|
||||||
|
|
||||||
|
Before using a style it needs to be initialized with :cpp:expr:`lv_style_init(&style1)`.
|
||||||
|
After that, properties can be added to configure the style. For example:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
static lv_style_t style1;
|
||||||
|
lv_style_init(&style1);
|
||||||
|
lv_style_set_bg_color(&style1, lv_color_hex(0xa03080));
|
||||||
|
lv_style_set_border_width(&style1, 2);
|
||||||
|
|
||||||
|
See :ref:`style_properties_overview` for more details.
|
||||||
|
|
||||||
|
See :ref:`style_properties` to see the full list.
|
||||||
|
|
||||||
|
Adding styles to the widgets
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
After that it can be added to widgets:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_add_style(my_button1, &style1, 0); /*0 means add to the main part and default state*/
|
||||||
|
lv_obj_add_style(my_checkbox1, &style1, LV_STATE_DISABLED); /*Add to checkbox's disabled state*/
|
||||||
|
lv_obj_add_style(my_slider1, &style1, LV_PART_KNOB | LV_STATE_PRESSED); /*Add to the slider's knob pressed state*/
|
||||||
|
|
||||||
|
Inheritance
|
||||||
|
-----------
|
||||||
|
|
||||||
|
Some properties (particularly the text-related ones) can be inherited. This
|
||||||
|
means if a property is not set in a Widget it will be searched for in
|
||||||
|
its parents. For example, you can set the font once in the screen's
|
||||||
|
style and all text on that screen will inherit it by default, unless the
|
||||||
|
font is specified on the widget or one of its parents.
|
||||||
|
|
||||||
|
Local styles
|
||||||
|
------------
|
||||||
|
|
||||||
|
Local style properties also can be added to Widgets. This creates a
|
||||||
|
style which resides inside the Widget and is used only by that Widget:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
lv_obj_set_style_bg_color(slider1, lv_color_hex(0x2080bb), LV_PART_INDICATOR | LV_STATE_PRESSED);
|
||||||
|
|
||||||
|
See :ref:`styles` for full details.
|
||||||
|
|
||||||
|
.. _basics_subjects:
|
||||||
|
|
||||||
|
Subjects and Observers
|
||||||
|
**********************
|
||||||
|
|
||||||
|
Subjects and Observers are powerful tools to easily create data bindings.
|
||||||
|
|
||||||
|
Subjects are global :cpp:expr:`lv_subject_t` variables that store integer, color, string, etc. values.
|
||||||
|
|
||||||
|
Either the UI or the application can subscribe to these subjects by creating *observer callbacks* that
|
||||||
|
are notified when the subject changes.
|
||||||
|
|
||||||
|
A widget can also subscribe to a subject. This way, when the widget is deleted, it will be automatically unsubscribed.
|
||||||
|
|
||||||
|
For some widgets, helper functions make it simple to connect them to subjects. E.g.:
|
||||||
|
:cpp:expr:`lv_slider_bind_value()`, :cpp:expr:`lv_label_bind_text()`.
|
||||||
|
|
||||||
|
In general, using subjects and observers is a way to connect various parts of the UI and make them dynamically
|
||||||
|
react to application data changes—or allow the application to react to UI changes.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
static void label_observer_cb(lv_observer_t * observer, lv_subject_t * subject)
|
||||||
|
{
|
||||||
|
lv_obj_t * label = lv_observer_get_target_obj(observer);
|
||||||
|
lv_label_set_text_fmt(label, "Progress: %d", lv_subject_get_int(subject));
|
||||||
|
}
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
static lv_subject_t subject1;
|
||||||
|
lv_subject_init_int(&subject1, 10);
|
||||||
|
|
||||||
|
lv_obj_t * label1 = lv_label_create(lv_screen_active());
|
||||||
|
/*lv_label_bind_text could have been used too*/
|
||||||
|
lv_subject_add_observer_obj(&subject1, label_observer_cb, label1, NULL);
|
||||||
|
|
||||||
|
lv_obj_t * slider1 = lv_slider_create(lv_screen_active());
|
||||||
|
lv_slider_bind_value(slider1, &subject1);
|
||||||
|
lv_obj_set_y(slider1, 30);
|
||||||
|
|
||||||
|
lv_subject_set_int(&subject1, 30);
|
||||||
|
|
||||||
|
Learn more on the documentation page of :ref:`Observers <observer_how_to_use>`.
|
||||||
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
.. _whats_next:
|
||||||
|
|
||||||
|
============
|
||||||
|
What's Next?
|
||||||
|
============
|
||||||
|
|
||||||
|
There are several good ways ways to gain deeper knowledge of LVGL. Here is one
|
||||||
|
recommended order of documents to read and things to play with while you are
|
||||||
|
advancing your knowledge:
|
||||||
|
|
||||||
|
1. If not already read, start with :ref:`introduction` page of
|
||||||
|
the documentation. (5 minutes)
|
||||||
|
2. Check out the `Online Demos`_ to see LVGL in action. (3 minutes)
|
||||||
|
3. If not already done, read the :ref:`learn_the_basics` (above). (15 minutes)
|
||||||
|
4. Set up an LVGL :ref:`simulator`. (10 minutes)
|
||||||
|
5. Have a look at some :ref:`examples` and their code.
|
||||||
|
6. :ref:`Add LVGL to your project <adding_lvgl_to_your_project>` or check out
|
||||||
|
the `ready-to-use Projects`_.
|
||||||
|
7. Read the :ref:`main_modules` pages to get a better understanding of the library. (2-3 hours)
|
||||||
|
8. Skim the documentation of :ref:`widgets` to see what is available.
|
||||||
|
9. If you have questions go to the `Forum`_.
|
||||||
|
10. Read the :ref:`contributing` guide to see how you can help to improve LVGL. (15 minutes)
|
||||||
|
|
||||||
|
|
||||||
|
.. _online demos: https://lvgl.io/demos
|
||||||
|
.. _ready-to-use projects: https://github.com/lvgl?q=lv_port_&type=&language=
|
||||||
|
.. _forum: https://forum.lvgl.io/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,334 +0,0 @@
|
|||||||
.. _introduction:
|
|
||||||
|
|
||||||
============
|
|
||||||
Introduction
|
|
||||||
============
|
|
||||||
|
|
||||||
LVGL (Light and Versatile Graphics Library) is a free and open-source graphics
|
|
||||||
library providing everything you need to create an embedded GUI with easy-to-use
|
|
||||||
graphical elements, beautiful visual effects, and a low memory footprint.
|
|
||||||
|
|
||||||
You :ref:`add LVGL to your project <adding_lvgl_to_your_project>`, provide it with
|
|
||||||
inputs and the method for pixels to flow to the display panel(s), and LVGL does the
|
|
||||||
heavy lifting in between.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Key features
|
|
||||||
************
|
|
||||||
|
|
||||||
- Powerful building blocks such as :ref:`buttons, charts, lists, sliders, images <widgets>`, etc.
|
|
||||||
- Advanced graphics with animations, anti-aliasing, opacity, smooth scrolling
|
|
||||||
- Various input devices such as touchpad, mouse, keyboard, encoder, etc.
|
|
||||||
- Multi-language support with UTF-8 encoding
|
|
||||||
- Multi-display support, even with mixed color formats
|
|
||||||
- Fully customizable graphic elements with CSS-like styles
|
|
||||||
- Hardware independent: use with any microcontroller or display
|
|
||||||
- Scalable: able to operate with little memory (64 kB Flash, 16 kB RAM)
|
|
||||||
- :ref:`OS <threading>`, external memory and :ref:`GPU <draw>` are supported but not required
|
|
||||||
- Single frame buffer operation even with advanced graphic effects
|
|
||||||
- Written in C for maximal compatibility (C++ compatible)
|
|
||||||
- :ref:`Simulator <simulator>` to start embedded GUI design on a PC without embedded hardware
|
|
||||||
- User code developed under simulator can be shared with firmware to make UI development more efficient.
|
|
||||||
- Binding to :ref:`MicroPython`
|
|
||||||
- Tutorials, examples, themes for rapid GUI design
|
|
||||||
- Documentation is available online
|
|
||||||
- Free and open-source under MIT license
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _requirements:
|
|
||||||
|
|
||||||
Requirements
|
|
||||||
************
|
|
||||||
|
|
||||||
Basically, every modern controller which is able to drive a display is suitable to
|
|
||||||
run LVGL. The minimal requirements are:
|
|
||||||
|
|
||||||
* 16, 32 or 64 bit microcontroller or processor
|
|
||||||
* > 16 MHz clock speed is recommended
|
|
||||||
* Flash/ROM: > 64 kB for the very essential components (> 180 kB is recommended)
|
|
||||||
* RAM:
|
|
||||||
* Static RAM usage: ~2 kB depending on the used features and Widget types
|
|
||||||
* stack: > 2kB (> 8 kB recommended)
|
|
||||||
* Dynamic data (heap): > 2 KB (> 48 kB is recommended if using many GUI Widgets).
|
|
||||||
Set by :c:macro:`LV_MEM_SIZE` in ``lv_conf.h``.
|
|
||||||
* Display buffer: > *"Horizontal resolution"* pixels (> 10 X *"Horizontal resolution"* is recommended)
|
|
||||||
* One frame buffer in the MCU or in an external display controller
|
|
||||||
* C99 or newer compiler
|
|
||||||
* Basic C (or C++) knowledge:
|
|
||||||
* `pointers <https://www.tutorialspoint.com/cprogramming/c_pointers.htm>`__.
|
|
||||||
* `structs <https://www.tutorialspoint.com/cprogramming/c_structures.htm>`__.
|
|
||||||
* `callbacks <https://www.geeksforgeeks.org/callbacks-in-c/>`__.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
*Memory usage may vary depending on architecture, compiler and build options.*
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
License
|
|
||||||
*******
|
|
||||||
|
|
||||||
The LVGL project (including all repositories) is licensed under the `MIT license
|
|
||||||
<https://github.com/lvgl/lvgl/blob/master/LICENCE.txt>`__. This means you can use it
|
|
||||||
even in commercial projects.
|
|
||||||
|
|
||||||
It is not mandatory, but we highly appreciate it if you write a few words about your
|
|
||||||
project in the `My projects <https://forum.lvgl.io/c/my-projects/10>`__ category of
|
|
||||||
the forum or a private message to `lvgl.io <https://lvgl.io/#contact>`__.
|
|
||||||
|
|
||||||
Although you can get LVGL for free there is a massive amount of work behind it. It's
|
|
||||||
created by a group of volunteers who made it available for you in their free time.
|
|
||||||
|
|
||||||
To make the LVGL project sustainable, please consider :ref:`contributing` to the
|
|
||||||
project. You can choose from many different ways of contributing. See
|
|
||||||
:ref:`contributing` such as simply writing a tweet about you using LVGL, fixing bugs,
|
|
||||||
translating the documentation, or even becoming a maintainer.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
FAQ
|
|
||||||
***
|
|
||||||
|
|
||||||
Where can I ask questions?
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
You can ask questions in the forum: https://forum.lvgl.io/.
|
|
||||||
|
|
||||||
We use `GitHub issues <https://github.com/lvgl/lvgl/issues>`_ for development related discussion.
|
|
||||||
You should use them only if your question or issue is tightly related to the development of the library.
|
|
||||||
|
|
||||||
Before posting a question, please read this FAQ section since you might find the answer to your issue here as well.
|
|
||||||
|
|
||||||
|
|
||||||
Is my MCU/hardware supported?
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Every MCU which is capable of driving a display via parallel port, SPI, RGB interface or anything else and fulfills the :ref:`requirements` is supported by LVGL.
|
|
||||||
|
|
||||||
This includes:
|
|
||||||
|
|
||||||
* "Common" MCUs like STM32F, STM32H, NXP Kinetis, LPC, iMX, dsPIC33, PIC32, SWM341 etc.
|
|
||||||
* Bluetooth, GSM, Wi-Fi modules like Nordic NRF, Espressif ESP32 and Raspberry Pi Pico W
|
|
||||||
* Linux with frame buffer device such as /dev/fb0. This includes Single-board computers like the Raspberry Pi
|
|
||||||
* Anything else with a strong enough MCU and a peripheral to drive a display
|
|
||||||
|
|
||||||
|
|
||||||
Is my display supported?
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
LVGL needs just one simple driver function to copy an array of pixels into a given area of the display.
|
|
||||||
If you can do this with your display then you can use it with LVGL.
|
|
||||||
|
|
||||||
Some examples of the supported display types:
|
|
||||||
|
|
||||||
* TFTs with 16 or 24 bit color depth
|
|
||||||
* Monitors with an HDMI port
|
|
||||||
* Small monochrome displays
|
|
||||||
* Gray-scale displays
|
|
||||||
* even LED matrices
|
|
||||||
* or any other display where you can control the color/state of the pixels
|
|
||||||
|
|
||||||
See the :ref:`display` section to learn more.
|
|
||||||
|
|
||||||
|
|
||||||
LVGL doesn't start, randomly crashes or nothing is drawn on the display. What can be the problem?
|
|
||||||
-------------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
* Try increasing :c:macro:`LV_MEM_SIZE`.
|
|
||||||
* Be sure your display works without LVGL. E.g. paint it to red on start up.
|
|
||||||
* Enable :ref:`logging`.
|
|
||||||
* Enable assertions in ``lv_conf.h`` (``LV_USE_ASSERT_...``).
|
|
||||||
* If you use an RTOS:
|
|
||||||
* Increase the stack size of the task that calls :cpp:func:`lv_timer_handler`.
|
|
||||||
* Be sure you are using one of the methods for thread management as described in :ref:`threading`.
|
|
||||||
|
|
||||||
|
|
||||||
My display driver is not called. What have I missed?
|
|
||||||
----------------------------------------------------
|
|
||||||
|
|
||||||
Be sure you are calling :cpp:expr:`lv_tick_inc(x)` as prescribed in
|
|
||||||
:ref:`tick_interface` and are calling :cpp:func:`lv_timer_handler` as prescribed in
|
|
||||||
:ref:`timer_handler`.
|
|
||||||
|
|
||||||
Learn more in the :ref:`tick_interface` and :ref:`timer_handler` sections.
|
|
||||||
|
|
||||||
|
|
||||||
Why is the display driver called only once? Only the upper part of the display is refreshed.
|
|
||||||
--------------------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
Be sure you are calling :cpp:expr:`lv_display_flush_ready(drv)` at the end of your
|
|
||||||
"*display flush callback*" as per :ref:`flush_callback` section.
|
|
||||||
|
|
||||||
|
|
||||||
Why do I see only garbage on the screen?
|
|
||||||
----------------------------------------
|
|
||||||
|
|
||||||
There is probably a bug in your display driver. Try the following code without using
|
|
||||||
LVGL. You should see a square with red-blue gradient.
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
#define BUF_W 20
|
|
||||||
#define BUF_H 10
|
|
||||||
|
|
||||||
lv_color_t buf[BUF_W * BUF_H];
|
|
||||||
lv_color_t * buf_p = buf;
|
|
||||||
uint16_t x, y;
|
|
||||||
for(y = 0; y < BUF_H; y++) {
|
|
||||||
lv_color_t c = lv_color_mix(LV_COLOR_BLUE, LV_COLOR_RED, (y * 255) / BUF_H);
|
|
||||||
for(x = 0; x < BUF_W; x++){
|
|
||||||
(*buf_p) = c;
|
|
||||||
buf_p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lv_area_t a;
|
|
||||||
a.x1 = 10;
|
|
||||||
a.y1 = 40;
|
|
||||||
a.x2 = a.x1 + BUF_W - 1;
|
|
||||||
a.y2 = a.y1 + BUF_H - 1;
|
|
||||||
my_flush_cb(NULL, &a, buf);
|
|
||||||
|
|
||||||
|
|
||||||
Why do I see nonsense colors on the screen?
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
The configured LVGL color format is probably not compatible with your display's color
|
|
||||||
format. Check :c:macro:`LV_COLOR_DEPTH` in *lv_conf.h*.
|
|
||||||
|
|
||||||
|
|
||||||
How do I speed up my UI?
|
|
||||||
------------------------
|
|
||||||
|
|
||||||
- Turn on compiler optimization and enable instruction- and data-caching if your MCU has them.
|
|
||||||
- Increase the size of the display buffer.
|
|
||||||
- Use two display buffers and flush the buffer with DMA (or similar peripheral) in the background.
|
|
||||||
- Increase the clock speed of the SPI or parallel port if you use them to drive the display.
|
|
||||||
- If your display has an SPI port consider changing to a model with a parallel interface because it has much higher throughput.
|
|
||||||
- Keep the display buffer in internal RAM (not in external SRAM) because LVGL uses it a lot and it should have fast access time.
|
|
||||||
|
|
||||||
|
|
||||||
How do I reduce flash/ROM usage?
|
|
||||||
--------------------------------
|
|
||||||
|
|
||||||
You can disable unused features (such as animations, file system, GPU etc.) and widget types in *lv_conf.h*.
|
|
||||||
|
|
||||||
If you are using GCC/CLANG you can add `-fdata-sections -ffunction-sections` compiler flags and `--gc-sections` linker flag to remove unused functions and variables from the final binary. If possible, add the `-flto` compiler flag to enable link-time-optimisation together with `-Os` for GCC or `-Oz` for CLANG.
|
|
||||||
|
|
||||||
|
|
||||||
How do I reduce RAM usage?
|
|
||||||
--------------------------
|
|
||||||
|
|
||||||
* Lower the size of the *Display buffer*.
|
|
||||||
* Reduce :c:macro:`LV_MEM_SIZE` in *lv_conf.h*. This memory is used when you create Widgets like buttons, labels, etc.
|
|
||||||
* To work with lower :c:macro:`LV_MEM_SIZE` you can create Widgets only when required and delete them when they are not needed anymore.
|
|
||||||
|
|
||||||
|
|
||||||
How do I use LVGL with an operating system?
|
|
||||||
-------------------------------------------
|
|
||||||
|
|
||||||
To work with an operating system where tasks can interrupt each other (preemptively),
|
|
||||||
you must ensure that no LVGL function call be called while another LVGL call is in
|
|
||||||
progress. There are several ways to do this. See the :ref:`threading` section to
|
|
||||||
learn more.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
The LVGL Repository
|
|
||||||
*******************
|
|
||||||
|
|
||||||
|
|
||||||
Repository layout
|
|
||||||
-----------------
|
|
||||||
|
|
||||||
All repositories of the LVGL project are hosted on `GitHub <https://github.com/lvgl>`_.
|
|
||||||
|
|
||||||
You will find these repositories there:
|
|
||||||
|
|
||||||
* `lvgl <https://github.com/lvgl/lvgl>`__: The library itself with many `examples <https://github.com/lvgl/lvgl/blob/master/examples/>`_ and `demos <https://github.com/lvgl/lvgl/blob/master/demos/>`__.
|
|
||||||
* `lv_drivers <https://github.com/lvgl/lv_drivers>`__: Display and input device drivers
|
|
||||||
* `blog <https://github.com/lvgl/blog>`__: Source of the `blog's site <https://blog.lvgl.io>`__
|
|
||||||
* `sim <https://github.com/lvgl/sim>`__: Source of the `online simulator's site <https://sim.lvgl.io>`__
|
|
||||||
* `lv_port_* <https://github.com/lvgl?q=lv_port&type=&language=>`__: LVGL ports to development boards or environments
|
|
||||||
* `lv_binding_* <https://github.com/lvgl?q=lv_binding&type=&language=l>`__: Bindings to other languages
|
|
||||||
|
|
||||||
|
|
||||||
Release policy
|
|
||||||
--------------
|
|
||||||
|
|
||||||
The core repositories follow the rules of `Semantic Versioning <https://semver.org/>`__:
|
|
||||||
|
|
||||||
* Major version: incompatible API changes. E.g. v5.0.0, v6.0.0
|
|
||||||
* Minor version: new but backward-compatible functionalities. E.g. v6.1.0, v6.2.0
|
|
||||||
* Patch version: backward-compatible bug fixes. E.g. v6.1.1, v6.1.2
|
|
||||||
|
|
||||||
Tags like `vX.Y.Z` are created for every release.
|
|
||||||
|
|
||||||
|
|
||||||
Release cycle
|
|
||||||
-------------
|
|
||||||
|
|
||||||
* Bug fixes: released on demand even weekly
|
|
||||||
* Minor releases: every 3-4 months
|
|
||||||
* Major releases: approximately yearly
|
|
||||||
|
|
||||||
|
|
||||||
Branches
|
|
||||||
--------
|
|
||||||
|
|
||||||
The core repositories have at least the following branches:
|
|
||||||
|
|
||||||
* `master`: latest version, patches are merged directly here
|
|
||||||
* `release/vX.Y`: stable versions of the minor releases
|
|
||||||
* `fix/some-description`: temporary branches for bug fixes
|
|
||||||
* `feat/some-description`: temporary branches for features
|
|
||||||
|
|
||||||
|
|
||||||
Change log
|
|
||||||
----------
|
|
||||||
|
|
||||||
The changes are recorded in :ref:`changelog`.
|
|
||||||
|
|
||||||
|
|
||||||
Version support
|
|
||||||
---------------
|
|
||||||
|
|
||||||
Before v8 the last minor release of each major series was supported for 1 year.
|
|
||||||
Starting from v8, every minor release is supported for 1 year.
|
|
||||||
|
|
||||||
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
| Version | Release date | Support end | Active |
|
|
||||||
+=========+==============+==============+========+
|
|
||||||
|v5.3 | 1 Feb, 2019 | 1 Feb, 2020 | No |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v6.1 | 26 Nov, 2019 | 26 Nov, 2020 | No |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v7.11 | 16 Mar, 2021 | 16 Mar, 2022 | No |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v8.0 | 1 Jun, 2021 | 1 Jun, 2022 | No |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v8.1 | 10 Nov, 2021 | 10 Nov, 2022 | No |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v8.2 | 31 Jan, 2022 | 31 Jan, 2023 | No |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v8.3 | 6 July, 2022 | 1 Jan, 2025 | No |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v8.4 | 19 Mar, 2024 | 20 Mar, 2025 | Yes |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v9.0 | 22 Jan, 2024 | 22 Jan, 2025 | Yes |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v9.1 | 20 Mar, 2024 | 20 Mar, 2025 | Yes |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|v9.2 | 26 Aug, 2024 | 26 Aug, 2025 | Yes |
|
|
||||||
+---------+--------------+--------------+--------+
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
API
|
|
||||||
***
|
|
||||||
|
|
||||||
.. API equals: LV_MEM_SIZE, lv_timer_handler, lv_tick_inc, lv_display_flush_wait_cb_t,
|
|
||||||
LV_COLOR_DEPTH
|
|
||||||
|
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
.. _faq:
|
||||||
|
|
||||||
|
|
||||||
|
===
|
||||||
|
FAQ
|
||||||
|
===
|
||||||
|
|
||||||
|
Where can I ask questions?
|
||||||
|
**************************
|
||||||
|
|
||||||
|
You can ask questions in the forum: https://forum.lvgl.io/.
|
||||||
|
|
||||||
|
We use `GitHub issues <https://github.com/lvgl/lvgl/issues>`_ for development related discussion.
|
||||||
|
You should use them only if your question or issue is tightly related to the development of the library.
|
||||||
|
|
||||||
|
Before posting a question, please read this FAQ section since you might find the answer to your issue here as well.
|
||||||
|
|
||||||
|
|
||||||
|
Is my MCU/hardware supported?
|
||||||
|
*****************************
|
||||||
|
|
||||||
|
Every MCU which is capable of driving a display via parallel port, SPI, RGB interface or anything else and fulfills the :ref:`requirements` is supported by LVGL.
|
||||||
|
|
||||||
|
This includes:
|
||||||
|
|
||||||
|
* "Common" MCUs like STM32F, STM32H, NXP Kinetis, LPC, iMX, dsPIC33, PIC32, SWM341 etc.
|
||||||
|
* Bluetooth, GSM, Wi-Fi modules like Nordic NRF, Espressif ESP32 and Raspberry Pi Pico W
|
||||||
|
* Linux with frame buffer device such as /dev/fb0. This includes Single-board computers like the Raspberry Pi
|
||||||
|
* Anything else with a strong enough MCU and a peripheral to drive a display
|
||||||
|
|
||||||
|
|
||||||
|
Is my display supported?
|
||||||
|
************************
|
||||||
|
|
||||||
|
LVGL needs just one simple driver function to copy an array of pixels into a given area of the display.
|
||||||
|
If you can do this with your display then you can use it with LVGL.
|
||||||
|
|
||||||
|
Some examples of the supported display types:
|
||||||
|
|
||||||
|
* TFTs with 16 or 24 bit color depth
|
||||||
|
* Monitors with an HDMI port
|
||||||
|
* Small monochrome displays
|
||||||
|
* Gray-scale displays
|
||||||
|
* even LED matrices
|
||||||
|
* or any other display where you can control the color/state of the pixels
|
||||||
|
|
||||||
|
See the :ref:`display` section to learn more.
|
||||||
|
|
||||||
|
|
||||||
|
LVGL doesn't start, randomly crashes or nothing is drawn on the display. What can be the problem?
|
||||||
|
*************************************************************************************************
|
||||||
|
|
||||||
|
* Try increasing :c:macro:`LV_MEM_SIZE`.
|
||||||
|
* Be sure your display works without LVGL. E.g. paint it to red on start up.
|
||||||
|
* Enable :ref:`logging`.
|
||||||
|
* Enable assertions in ``lv_conf.h`` (``LV_USE_ASSERT_...``).
|
||||||
|
* If you use an RTOS:
|
||||||
|
* Increase the stack size of the task that calls :cpp:func:`lv_timer_handler`.
|
||||||
|
* Be sure you are using one of the methods for thread management as described in :ref:`threading`.
|
||||||
|
|
||||||
|
|
||||||
|
My display driver is not called. What have I missed?
|
||||||
|
****************************************************
|
||||||
|
|
||||||
|
Be sure you are calling :cpp:expr:`lv_tick_inc(x)` as prescribed in
|
||||||
|
:ref:`tick_interface` and are calling :cpp:func:`lv_timer_handler` as prescribed in
|
||||||
|
:ref:`timer_handler`.
|
||||||
|
|
||||||
|
Learn more in the :ref:`tick_interface` and :ref:`timer_handler` sections.
|
||||||
|
|
||||||
|
|
||||||
|
Why is the display driver called only once? Only the upper part of the display is refreshed.
|
||||||
|
********************************************************************************************
|
||||||
|
|
||||||
|
Be sure you are calling :cpp:expr:`lv_display_flush_ready(drv)` at the end of your
|
||||||
|
"*display flush callback*" as per :ref:`flush_callback` section.
|
||||||
|
|
||||||
|
|
||||||
|
Why do I see only garbage on the screen?
|
||||||
|
****************************************
|
||||||
|
|
||||||
|
There is probably a bug in your display driver. Try the following code without using
|
||||||
|
LVGL. You should see a square with red-blue gradient.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
#define BUF_WIDTH 255
|
||||||
|
uint16_t buf[BUF_WIDTH];
|
||||||
|
uint32_t i;
|
||||||
|
for(i = 0; i < BUF_WIDTH; i++) {
|
||||||
|
lv_color_t c = lv_color_mix(lv_color_hex(0xff0000), lv_color_hex(0x00ff00), i);
|
||||||
|
buf[i] = lv_color_to_u16(c);
|
||||||
|
|
||||||
|
lv_area_t a;
|
||||||
|
a.x1 = 5;
|
||||||
|
a.x2 = a.x1 + BUF_WIDTH - 1;
|
||||||
|
a.y1 = 10 + i;
|
||||||
|
a.y2 = 10 + i;
|
||||||
|
my_flush_cb(NULL, &a, (void*) buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Why do I see nonsense colors on the screen?
|
||||||
|
*******************************************
|
||||||
|
|
||||||
|
The configured LVGL color format is probably not compatible with your display's color
|
||||||
|
format. Check :c:macro:`LV_COLOR_DEPTH` in *lv_conf.h*.
|
||||||
|
|
||||||
|
|
||||||
|
How do I speed up my UI?
|
||||||
|
************************
|
||||||
|
|
||||||
|
- Turn on compiler optimization and enable instruction- and data-caching if your MCU has them.
|
||||||
|
- Increase the size of the display buffer.
|
||||||
|
- Use two display buffers and flush the buffer with DMA (or similar peripheral) in the background.
|
||||||
|
- Increase the clock speed of the SPI or parallel port if you use them to drive the display.
|
||||||
|
- If your display has an SPI port consider changing to a model with a parallel interface because it has much higher throughput.
|
||||||
|
- Keep the display buffer in internal RAM (not in external SRAM) because LVGL uses it a lot and it should have fast access time.
|
||||||
|
|
||||||
|
|
||||||
|
How do I reduce flash/ROM usage?
|
||||||
|
********************************
|
||||||
|
|
||||||
|
You can disable unused features (such as animations, file system, GPU etc.) and widget types in *lv_conf.h*.
|
||||||
|
|
||||||
|
If you are using GCC/CLANG you can add `-fdata-sections -ffunction-sections` compiler flags and `--gc-sections` linker flag to remove unused functions and variables from the final binary. If possible, add the `-flto` compiler flag to enable link-time-optimisation together with `-Os` for GCC or `-Oz` for CLANG and newer GCC versions.
|
||||||
|
|
||||||
|
|
||||||
|
How do I reduce RAM usage?
|
||||||
|
**************************
|
||||||
|
|
||||||
|
* Lower the size of the *Display buffer*.
|
||||||
|
* Reduce :c:macro:`LV_MEM_SIZE` in *lv_conf.h*. This memory is used when you create Widgets like buttons, labels, etc.
|
||||||
|
* To work with lower :c:macro:`LV_MEM_SIZE` you can create Widgets only when required and delete them when they are not needed anymore.
|
||||||
|
|
||||||
|
|
||||||
|
How do I use LVGL with an operating system?
|
||||||
|
*******************************************
|
||||||
|
|
||||||
|
To work with an operating system where tasks can interrupt each other (preemptively),
|
||||||
|
you must ensure that no LVGL function call be called while another LVGL call is in
|
||||||
|
progress. There are several ways to do this. See the :ref:`threading` section to
|
||||||
|
learn more.
|
||||||
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
.. _introduction:
|
||||||
|
|
||||||
|
============
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
LVGL (Light and Versatile Graphics Library) is a free and open-source graphics
|
||||||
|
library providing everything you need to create an embedded GUI with easy-to-use
|
||||||
|
graphical elements, beautiful visual effects, and a low memory footprint.
|
||||||
|
|
||||||
|
You :ref:`add LVGL to your project <adding_lvgl_to_your_project>`, provide it with
|
||||||
|
inputs and the method for pixels to flow to the display panel(s), and LVGL does the
|
||||||
|
heavy lifting in between.
|
||||||
|
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
key_features
|
||||||
|
requirements
|
||||||
|
license
|
||||||
|
faq
|
||||||
|
repo
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
.. _key_features:
|
||||||
|
|
||||||
|
============
|
||||||
|
Key features
|
||||||
|
============
|
||||||
|
|
||||||
|
- Powerful building blocks such as :ref:`buttons, charts, lists, sliders, images <widgets>`, etc.
|
||||||
|
- Advanced graphics with animations, anti-aliasing, opacity, smooth scrolling
|
||||||
|
- Various input devices such as touchpad, mouse, keyboard, encoder, etc.
|
||||||
|
- Multi-language support with UTF-8 encoding
|
||||||
|
- Multi-display support, even with mixed color formats
|
||||||
|
- Fully customizable graphic elements with CSS-like styles
|
||||||
|
- Hardware independent: use with any microcontroller or display
|
||||||
|
- Scalable: able to operate with little memory (64 kB Flash, 16 kB RAM)
|
||||||
|
- :ref:`OS <threading>`, external memory and :ref:`GPU <draw>` are supported but not required
|
||||||
|
- Single frame buffer operation even with advanced graphic effects
|
||||||
|
- Written in C for maximal compatibility (C++ compatible)
|
||||||
|
- :ref:`Simulator <simulator>` to start embedded GUI design on a PC without embedded hardware
|
||||||
|
- User code developed under simulator can be shared with firmware to make UI development more efficient.
|
||||||
|
- Binding to :ref:`MicroPython`
|
||||||
|
- Tutorials, examples, themes for rapid GUI design
|
||||||
|
- Documentation is available online
|
||||||
|
- Free and open-source under MIT license
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
.. license:
|
||||||
|
|
||||||
|
=======
|
||||||
|
License
|
||||||
|
=======
|
||||||
|
|
||||||
|
The LVGL project (including all repositories) is licensed under the `MIT license
|
||||||
|
<https://github.com/lvgl/lvgl/blob/master/LICENCE.txt>`__. This means you can use it
|
||||||
|
even in commercial projects.
|
||||||
|
|
||||||
|
It is not mandatory, but we highly appreciate it if you write a few words about your
|
||||||
|
project in the `My projects <https://forum.lvgl.io/c/my-projects/10>`__ category of
|
||||||
|
the forum or a private message to `lvgl.io <https://lvgl.io/#contact>`__.
|
||||||
|
|
||||||
|
Although you can get LVGL for free there is a massive amount of work behind it. It's
|
||||||
|
created by a group of volunteers who made it available for you in their free time.
|
||||||
|
|
||||||
|
To make the LVGL project sustainable, please consider :ref:`contributing` to the
|
||||||
|
project. You can choose from many different ways of contributing. See
|
||||||
|
:ref:`contributing` such as simply writing a tweet about you using LVGL, fixing bugs,
|
||||||
|
translating the documentation, or even becoming a maintainer.
|
||||||
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
.. _repository:
|
||||||
|
|
||||||
|
===================
|
||||||
|
The LVGL Repository
|
||||||
|
===================
|
||||||
|
|
||||||
|
|
||||||
|
Repository layout
|
||||||
|
*****************
|
||||||
|
|
||||||
|
All repositories of the LVGL project are hosted on `GitHub <https://github.com/lvgl>`_.
|
||||||
|
|
||||||
|
You will find these repositories there:
|
||||||
|
|
||||||
|
* `lvgl <https://github.com/lvgl/lvgl>`__: The library itself with many `examples <https://github.com/lvgl/lvgl/blob/master/examples/>`_ and `demos <https://github.com/lvgl/lvgl/blob/master/demos/>`__.
|
||||||
|
* `blog <https://github.com/lvgl/blog>`__: Source of the `blog's site <https://blog.lvgl.io>`__
|
||||||
|
* `sim <https://github.com/lvgl/sim>`__: Source of the `online simulator's site <https://sim.lvgl.io>`__
|
||||||
|
* `lv_port_* <https://github.com/lvgl?q=lv_port&type=&language=>`__: LVGL ports to development boards or environments
|
||||||
|
* `lv_binding_* <https://github.com/lvgl?q=lv_binding&type=&language=l>`__: Bindings to other languages
|
||||||
|
|
||||||
|
|
||||||
|
Release policy
|
||||||
|
**************
|
||||||
|
|
||||||
|
|
||||||
|
The core repositories follow the rules of `Semantic Versioning <https://semver.org/>`__:
|
||||||
|
|
||||||
|
* Major version: incompatible API changes. E.g. v5.0.0, v6.0.0
|
||||||
|
* Minor version: new but backward-compatible functionalities. E.g. v6.1.0, v6.2.0
|
||||||
|
* Patch version: backward-compatible bug fixes. E.g. v6.1.1, v6.1.2
|
||||||
|
|
||||||
|
Tags like `vX.Y.Z` are created for every release.
|
||||||
|
|
||||||
|
|
||||||
|
Release cycle
|
||||||
|
*************
|
||||||
|
|
||||||
|
* Bug fixes: released on demand even weekly
|
||||||
|
* Minor releases: every 3-4 months
|
||||||
|
* Major releases: approximately yearly
|
||||||
|
|
||||||
|
|
||||||
|
Branches
|
||||||
|
********
|
||||||
|
|
||||||
|
|
||||||
|
The core repositories have at least the following branches:
|
||||||
|
|
||||||
|
* `master`: latest version, patches are merged directly here
|
||||||
|
* `release/vX.Y`: stable versions of the minor releases
|
||||||
|
|
||||||
|
|
||||||
|
Change log
|
||||||
|
**********
|
||||||
|
|
||||||
|
The changes are recorded in :ref:`changelog`.
|
||||||
|
|
||||||
|
|
||||||
|
Version support
|
||||||
|
***************
|
||||||
|
|
||||||
|
|
||||||
|
Before v8 the last minor release of each major series was supported for 1 year.
|
||||||
|
Starting from v8, every minor release is supported for 1 year.
|
||||||
|
|
||||||
|
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
| Version | Release date | Support end | Active |
|
||||||
|
+=========+==============+==============+========+
|
||||||
|
|v5.3 | 1 Feb, 2019 | 1 Feb, 2020 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v6.1 | 26 Nov, 2019 | 26 Nov, 2020 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v7.11 | 16 Mar, 2021 | 16 Mar, 2022 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v8.0 | 1 Jun, 2021 | 1 Jun, 2022 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v8.1 | 10 Nov, 2021 | 10 Nov, 2022 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v8.2 | 31 Jan, 2022 | 31 Jan, 2023 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v8.3 | 6 July, 2022 | 1 Jan, 2025 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v8.4 | 19 Mar, 2024 | 20 Mar, 2025 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v9.0 | 22 Jan, 2024 | 22 Jan, 2025 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v9.1 | 20 Mar, 2024 | 20 Mar, 2025 | No |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v9.2 | 26 Aug, 2024 | 26 Aug, 2025 | Yes |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|v9.3 | 3 June, 2025 | 3 June, 2026 | Yes |
|
||||||
|
+---------+--------------+--------------+--------+
|
||||||
|
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
.. _requirements:
|
||||||
|
|
||||||
|
============
|
||||||
|
Requirements
|
||||||
|
============
|
||||||
|
|
||||||
|
Basically, every modern controller which is able to drive a display is suitable to
|
||||||
|
run LVGL. The minimal requirements are:
|
||||||
|
|
||||||
|
* 16, 32 or 64 bit microcontroller or processor
|
||||||
|
* > 16 MHz clock speed is recommended
|
||||||
|
* Flash/ROM: > 64 kB for the very essential components (> 180 kB is recommended)
|
||||||
|
* RAM:
|
||||||
|
* Static RAM usage: ~2 kB depending on the used features and Widget types
|
||||||
|
* stack: > 2kB (> 8 kB recommended)
|
||||||
|
* Dynamic data (heap): > 2 KB (> 48 kB is recommended if using many GUI Widgets).
|
||||||
|
Set by :c:macro:`LV_MEM_SIZE` in ``lv_conf.h``.
|
||||||
|
* Display buffer: > *"Horizontal resolution"* pixels (> 10 X *"Horizontal resolution"* is recommended)
|
||||||
|
* One frame buffer in the MCU or in an external display controller
|
||||||
|
* C99 or newer compiler
|
||||||
|
* Basic C (or C++) knowledge:
|
||||||
|
* `pointers <https://www.tutorialspoint.com/cprogramming/c_pointers.htm>`__.
|
||||||
|
* `structs <https://www.tutorialspoint.com/cprogramming/c_structures.htm>`__.
|
||||||
|
* `callbacks <https://www.geeksforgeeks.org/callbacks-in-c/>`__.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
*Memory usage may vary depending on architecture, compiler and build options.*
|
||||||
|
|
||||||
Reference in New Issue
Block a user