Baxter Builds

How to Use Micropython LVGL Themes

February 6, 2023 by Baxter

two buttons each with different themes applied to them.

Applying individual styles to every object on your screen is a lot of work. Because of how annoying this process is LVGL has super styles aka themes. You apply a theme to your display, and it styles every object on your screen.

Today we will work through how to create a custom theme and modify an existing theme.

How Themes Work

Themes are actually a function. Essentially a you create a function, and every time an object is created your function is called. Inside that function, you check what type of object was created and then apply a style to it.

Setting Up a Micropython Screen

Because there are so many different screens out there, I can’t add support for all of them to the example, so to make the example work, you will need to add your screen’s setup code to the beginning of it.

There is a little more information on this process at How to get a LVGL Micropython Screen to Work if you aren’t familiar on how it’s done.

Here is the example

import lvgl

display = lvgl.disp_get_default()
defualt_theme = lvgl.theme_get_from_obj(lvgl.scr_act())

def apply(th,obj):
    if obj.get_class() == lvgl.btn_class:
        obj.set_style_bg_color(lvgl.color_hex(0x009900),0)

theme = lvgl.theme_t()
theme.set_parent(defualt_theme)
theme.set_apply_cb(apply)

display.set_theme(theme)


btn = lvgl.btn(lvgl.scr_act())
btn.center()
btn.set_size(60,40)

gen_theme = lvgl.theme_default_init(display,lvgl.color_hex(0x990000),lvgl.color_hex(0x00ff00),False,lvgl.font_montserrat_16)

display.set_theme(gen_theme)

btn = lvgl.btn(lvgl.scr_act())
btn.align(lvgl.ALIGN.CENTER,0,60)
btn.set_size(60,40)

Understanding This Code

Just looking at a block of code is not always very informational. To make how this micropython code works more clear, lets walk through the lines of code above and see what they do.

The Setup

Of course before we can use LVGL we need to import it. This is also a good spot to put your screen setup code.

import lvgl

We also need to retrieve the active screen object. Themes are applied to physical screens, so if you have more than one screen connected to your board, your are going to need to apply a theme to each one.

display = lvgl.disp_get_default()

Custom Themes

Lets create a custom theme. To make this theme simple, it will only target LVGL buttons, so we will use the default themes settings for all the other widgets. First we are going to retrieve the default theme.

defualt_theme = lvgl.theme_get_from_obj(lvgl.scr_act())

Next we create the theme’s function.

def apply(th,obj):

Inside that function we check if the current object is a button.

    if obj.get_class() == lvgl.btn_class:

If it is, we change the buttons color to green.

        obj.set_style_bg_color(lvgl.color_hex(0x009900),0)

Now we create a empty theme object.

theme = lvgl.theme_t()

Then we set its parent to the default theme any thing our theme does not deal with the parent theme takes care of.

theme.set_parent(defualt_theme)

After that we set the themes function to the function we created earlier.

theme.set_apply_cb(apply)

Lastly we add our theme to the the screen.

display.set_theme(theme)

The Button

Our new theme is applied but nothing is actually using it. Lets create button to show its working.

btn = lvgl.btn(lvgl.scr_act())
btn.center()
btn.set_size(60,40)

Generating a Theme

Manually creating a theme that styles every widget takes a lot of work, so LVGL comes with some pre-made themes that you can modify to your liking.

Making a new theme, only takes one line of code.

gen_theme = lvgl.theme_default_init(display,lvgl.color_hex(0x990000),lvgl.color_hex(0x00ff00),False,lvgl.font_montserrat_16)

The theme_default_init() function takes five arguments. The first argument is the active display. The other four arguments are explained below.

Argument Value Controls
Primary Color Any LVGL Color the color of most objects
Secondary Color Any LVGL Color the color of a few objects
Dark/Light Mode True or False whether LVGL uses dark or light colors
Font Any LVGL Font the default font of LVGL

With that one line of code we have generated a complete theme that works for all widgets, but we still need to apply it to the screen to see it work.

display.set_theme(gen_theme)

One Last Button

Of course, we need to create one more button to show that our theme is working.

btn = lvgl.btn(lvgl.scr_act())
btn.align(lvgl.ALIGN.CENTER,0,60)
btn.set_size(60,40)

Things To Think About

One obvious question that comes up, if we change the theme why doesn’t every object on the screen get that new theme applied to it. The answer to that question is I don’t now. Sometimes it seems that adding a theme does overrides the current theme and some time it seems to let the old one exist in the background.

We looked at two ways to create themes today. The last one was clearly easier and is the best option for normal use. The first method should really only be used, if you need an extremely custom theme.

If you like LVGL Themes then you might like LVGL Drawing Descriptors. They are another great way to customize your projects.

Filed Under: Micropython

Recent Posts

  • How to Shorten Your Micropython LVGL Code
  • FreeRTOS Mutex Example
  • FreeRTOS Task Notification Example
  • FreeRTOS Queue Example
  • FreeRTOS Semaphore Example

Categories

  • Arduino
  • ESP32 Web Page
  • FreeRTOS
  • LEGO Technic
  • LEGO tips
  • LEGO war robots
  • Lego's
  • Legos
  • LEGOS-build your own
  • Micropython

Copyright © 2025 · Minimum Pro Theme on Genesis Framework · WordPress · Log in