LVGL
badge_2024_micropython is built with LVLG v9.1 included
links
- lvgl homepage https://lvgl.io/
- lvgl documentation https://docs.lvgl.io/9.1/
python examples (v8.4)
Unfortunately for v9.x the python examples are not available any more
This are the main differences between v8.x and v9.x Changelog and more specific api-changes
- lvgl live python examples (v8.4) https://docs.lvgl.io/8.4/examples.html
- lvgl python examples source code (v8.4) (search for *.py files) https://github.com/lvgl/lvgl/tree/v8.4.0/examples
online simulator
There is an online micropython + lvgl (v9.0) simulator available
https://sim.lvgl.io/v9.0/micropython/ports/webassembly/index.html
This is very convenient to prototype new screens
Simulator Examples
button
# Initialize
import display_driver
import lvgl as lv
disp = lv.display_get_default()
disp.set_resolution(296,240)
# 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)
button in a class with callback, remembering state
# Initialize
import display_driver
import lvgl as lv
disp = lv.display_get_default()
disp.set_resolution(296,240)
class CounterBtn:
def __init__(self):
screen = lv.screen_active()
screen.set_style_bg_color(lv.palette_darken(lv.PALETTE.GREY, 4), lv.PART.MAIN)
self.btn = lv.button(screen)
self.btn.align(lv.ALIGN.CENTER, 0, 0)
self.lbl = lv.label(self.btn)
self.lbl.set_text("Button")
self.cnt = 0
self.btn.add_event_cb(self.btn_cb, lv.EVENT.ALL, None)
def btn_cb(self, evt):
code = evt.get_code()
if code == lv.EVENT.CLICKED:
self.cnt += 1
print(self.cnt)
self.lbl.set_text("Button: " + str(self.cnt))
counter_btn = CounterBtn()
wifi-config screen
# Initialize
import display_driver
import lvgl as lv
disp = lv.display_get_default()
disp.set_resolution(296,240)
class TextArea:
def __init__(self, screen):
self._screen = screen
self.ta = lv.textarea(screen)
self.ta.add_event_cb(self._ta_event_cb, lv.EVENT.ALL, None)
self._kb = None
def _ta_event_cb(self, event):
code = event.get_code()
if code == lv.EVENT.CLICKED or code == lv.EVENT.FOCUSED:
if self._kb is None:
# create keyboard
self._kb = lv.keyboard(self._screen)
self._kb.set_size(self._screen.get_width(), int(self._screen.get_height()/2) )
self._kb.align_to(self.ta, lv.ALIGN.OUT_BOTTOM_MID, 0, 0)
self._kb.set_x(0)
self._kb.set_textarea(self.ta)
self._kb.add_event_cb(self._kb_event_cb, lv.EVENT.ALL, None)
elif code == lv.EVENT.DEFOCUSED:
if self._kb is not None:
self._kb.delete()
self._kb = None
def _kb_event_cb(self, event):
code = event.get_code()
if code == lv.EVENT.READY or code == lv.EVENT.CANCEL:
self.ta.send_event(lv.EVENT.DEFOCUSED, self.ta)
class ButtonLabel:
def __init__(self, screen, label, cb):
btn = lv.button(screen)
self.btn = btn
btn.set_height(30)
lbl = lv.label(btn)
lbl.set_text(label)
lbl.align(lv.ALIGN.CENTER, 0, 0)
btn.add_event_cb(self._bt_event_cb, lv.EVENT.CLICKED, None)
self.cb = cb
def _bt_event_cb(self, event):
# code = event.get_code()
self.cb()
class WifiScreen:
def __init__(self):
self._screen = lv.obj()
self._construct()
def load(self):
lv.screen_load(self._screen)
def _save_cb(self):
ssid = self.ss_ta.ta.get_text()
key = self.key_ta.ta.get_text()
print(f"{ssid=}, {key=}")
# TODO save
def _cancel_cb(self):
print("Cancel")
#home_screen = fri3d.screens.home.HomeScreen()
#home_screen.load()
def _construct(self):
screen = self._screen
# title
title = lv.label(screen)
title.set_text("Wifi Configuration")
title.align(lv.ALIGN.TOP_MID, 0, 0)
# ssid textarea
ss_ta = TextArea(screen)
self.ss_ta = ss_ta
ss_ta.ta.set_text("")
ss_ta.ta.set_one_line(True)
ss_ta.ta.set_width(lv.pct(50))
ss_ta.ta.set_pos(100, 20)
# ssid label
ss_lbl = lv.label(screen)
ss_lbl.set_text("SSID:")
ss_lbl.align_to(ss_ta.ta, lv.ALIGN.OUT_LEFT_MID, -5, 0)
# key textarea
key_ta = TextArea(screen)
self.key_ta = key_ta
key_ta.ta.set_text("")
key_ta.ta.set_password_mode(True)
key_ta.ta.set_one_line(True)
key_ta.ta.set_width(lv.pct(50))
key_ta.ta.set_pos(100, 60)
# key label
key_lbl = lv.label(screen)
key_lbl.set_text("Key:")
key_lbl.align_to(key_ta.ta, lv.ALIGN.OUT_LEFT_MID, -5, 0)
# save button
sv = ButtonLabel(screen, lv.SYMBOL.OK + " Save", self._save_cb)
sv.btn.align(lv.ALIGN.RIGHT_MID, -5, 0)
# cancel button
cancel = ButtonLabel(screen, lv.SYMBOL.CLOSE + " Cancel", self._cancel_cb)
cancel.btn.align(lv.ALIGN.LEFT_MID, 5, 0)
w = WifiScreen()
w.load()
canvas
red border around a golden background
# Initialize
import display_driver
import lvgl as lv
disp = lv.display_get_default()
disp.set_resolution(296,240)
scr = lv.screen_active()
buf = lv.draw_buf_create(scr.get_width(),scr.get_height(),lv.COLOR_FORMAT.RGB565, lv.STRIDE_AUTO)
canvas = lv.canvas(scr)
canvas.set_draw_buf(buf)
canvas.center()
layer = lv.layer_t()
canvas.init_layer(layer)
dsc = lv.draw_rect_dsc_t()
dsc.bg_color = lv.color_hex(0xffbf00)
dsc.bg_opa = lv.OPA.COVER
dsc.border_color = lv.palette_main(lv.PALETTE.RED)
dsc.border_width = 2
dsc.border_side = lv.BORDER_SIDE.TOP | lv.BORDER_SIDE.LEFT | lv.BORDER_SIDE.RIGHT | lv.BORDER_SIDE.BOTTOM
dsc.border_opa = lv.OPA.COVER
dsc.radius = 61
a = lv.area_t()
a.x1 = 0
a.y1 = 0
a.x2 = 295
a.y2 = 239
lv.draw_rect(layer, dsc, a)
canvas.finish_layer(layer)
real examples
load png image
# load fri3d_logo-min.png
png = open('fri3d_logo-min.png', 'rb')
data = png.read()
png.close()
img = lv.image(lv.screen_active())
imgd = lv.image_dsc_t()
imgd.header.cf = lv.COLOR_FORMAT.ARGB8888
imgd.header.w = 240
imgd.header.h = 240
imgd.data = data
imgd.data_size = len(data)
img.set_src(imgd)
img.align(lv.ALIGN.CENTER, 0, 0)