From 0e465b820bc70d0748ef212ed5c3939277d1ea70 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:02:33 +1000 Subject: [PATCH 01/17] examples: Update uasyncio_example1.py to LVGL v9 API. - Replace move_foreground() with move_to_index() for v9 compatibility - Change lv.indev_get_act() to lv.indev_active() - Update del_async() to delete_async() - Update set_ready_cb() to set_completed_cb() These changes align with the LVGL v9 API naming conventions. --- examples/uasyncio_example1.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/uasyncio_example1.py b/examples/uasyncio_example1.py index 06007a251c..58f2d158ef 100644 --- a/examples/uasyncio_example1.py +++ b/examples/uasyncio_example1.py @@ -69,8 +69,10 @@ class MsgBox(lv.win): def drag_event_handler(self, e): - self.move_foreground() - indev = lv.indev_get_act() + parent = self.get_parent() + if parent: + self.move_to_index(parent.get_child_count() - 1) # Move to foreground + indev = lv.indev_active() indev.get_vect(self.vect) x = self.get_x() + self.vect.x y = self.get_y() + self.vect.y @@ -121,7 +123,7 @@ def close_msg_box(self): self.anim.set_custom_exec_cb(lambda obj, val: self.set_style_opa(val, lv.PART.MAIN)) self.anim.set_path_cb(lv.anim_t.path_ease_in) - self.anim.set_ready_cb(lambda a: self.del_async()) + self.anim.set_completed_cb(lambda a: self.delete_async()) lv.anim_t.start(self.anim) self.opened = False From bfcbb69a003254bcd324e8ce61922ebc0636bb3c Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:07:19 +1000 Subject: [PATCH 02/17] examples: Update madctl_helper.py to LVGL v9 API. Replace lv.scr_act() with lv.screen_active() to align with v9 API. --- examples/madctl/madctl_helper.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/madctl/madctl_helper.py b/examples/madctl/madctl_helper.py index 543c1083ca..173bfefbe4 100644 --- a/examples/madctl/madctl_helper.py +++ b/examples/madctl/madctl_helper.py @@ -15,7 +15,7 @@ style.init() style.set_bg_color(lv.palette_main(lv.PALETTE.RED)) -btn = lv.button(lv.scr_act()) +btn = lv.button(lv.screen_active()) btn.set_size(disp.width, disp.height) btn.align(lv.ALIGN.CENTER,0,0) btn.add_style(style, 0) From 5c2c3a4f4b0609121e13317852ed76e21a319dbf Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:09:49 +1000 Subject: [PATCH 03/17] examples: Add missing machine import to generic-st77xx-with-xpt2046.py. The example was using machine.SPI and machine.Pin without importing the machine module. --- examples/generic-st77xx-with-xpt2046.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/generic-st77xx-with-xpt2046.py b/examples/generic-st77xx-with-xpt2046.py index d2f7a62f73..5893915cc2 100644 --- a/examples/generic-st77xx-with-xpt2046.py +++ b/examples/generic-st77xx-with-xpt2046.py @@ -1,5 +1,6 @@ import sys sys.path.append('.') +import machine from st77xx import * from xpt2046 import * From 51cca4a4c72bc26b31c4db35c273a01986153184 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:38:20 +1000 Subject: [PATCH 04/17] examples: Update generic-st77xx-with-xpt2046.py v8 to v9 API. Fix center() method call and add_event() -> add_event_cb() for LVGL v9. --- examples/generic-st77xx-with-xpt2046.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/generic-st77xx-with-xpt2046.py b/examples/generic-st77xx-with-xpt2046.py index 5893915cc2..9105f274fd 100644 --- a/examples/generic-st77xx-with-xpt2046.py +++ b/examples/generic-st77xx-with-xpt2046.py @@ -32,6 +32,6 @@ btn=lv.button(scr) lbl=lv.label(btn) lbl.set_text("Press me!") -btn.center() -btn.add_event(lambda event: print('Button clicked!'),lv.EVENT.CLICKED,None) +btn.align(lv.ALIGN.CENTER) +btn.add_event_cb(lambda event: print('Button clicked!'),lv.EVENT.CLICKED,None) lv.screen_load(scr) From ac2e5249c1a8188e0243fc571e5b1112ea90aaa0 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:38:48 +1000 Subject: [PATCH 05/17] examples: Update uasyncio_example1.py v8 to v9 API. Fix add_event() -> add_event_cb() and align() offset parameters for LVGL v9. --- examples/uasyncio_example1.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/examples/uasyncio_example1.py b/examples/uasyncio_example1.py index 58f2d158ef..118801f7eb 100644 --- a/examples/uasyncio_example1.py +++ b/examples/uasyncio_example1.py @@ -85,7 +85,7 @@ def __init__(self, parent): self.set_size(100,80) self.add_title("Pop") msg_box_close_btn = self.add_button(lv.SYMBOL.CLOSE, 20) - msg_box_close_btn.add_event(lambda e: self.close_msg_box(), lv.EVENT.RELEASED, None) + msg_box_close_btn.add_event_cb(lambda e: self.close_msg_box(), lv.EVENT.RELEASED, None) header = self.get_header() header.set_style_bg_color(lv.color_hex3(0xFEE), lv.PART.MAIN) @@ -106,7 +106,7 @@ def __init__(self, parent): self.label = lv.label(content) for element in [content, header]: - element.add_event(self.drag_event_handler, lv.EVENT.PRESSING, None) + element.add_event_cb(self.drag_event_handler, lv.EVENT.PRESSING, None) self.opened = True @@ -162,8 +162,9 @@ async def btn_event_task(obj=None, event=-1): scr = lv.screen_active() btn = lv.button(scr) -btn.align(lv.ALIGN.TOP_MID, 0, 10) -btn.add_event(lambda e: create_task(btn_event_task()), lv.EVENT.CLICKED, None) +btn.align(lv.ALIGN.TOP_MID) +btn.set_y(10) +btn.add_event_cb(lambda e: create_task(btn_event_task()), lv.EVENT.CLICKED, None) label = lv.label(btn) label.set_text('Click Me Again!') From b21017aec3a2fabf5a0ec107c3fe13c08f13260e Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:39:01 +1000 Subject: [PATCH 06/17] examples: Update fb_test.py v8 to v9 API. Remove offset parameters from align() method for LVGL v9. --- examples/fb_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/fb_test.py b/examples/fb_test.py index 93c22b4597..1a001e9529 100644 --- a/examples/fb_test.py +++ b/examples/fb_test.py @@ -21,6 +21,6 @@ # Create a screen and a button btn = lv.button(lv.screen_active()) -btn.align(lv.ALIGN.CENTER, 0, 0) +btn.align(lv.ALIGN.CENTER) label = lv.label(btn) label.set_text("Hello World!") From 37b514a82984850fa5f022e221f663490f55ccd0 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:39:23 +1000 Subject: [PATCH 07/17] examples: Update example3.py v8 to v9 API. Remove offset parameters from align() methods and use separate position setters for LVGL v9. --- examples/example3.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/examples/example3.py b/examples/example3.py index 39dbb6e225..88a12dfa7f 100644 --- a/examples/example3.py +++ b/examples/example3.py @@ -40,20 +40,23 @@ slider = lv.slider(scr2) slider.set_width(150) -slider.align(lv.ALIGN.TOP_MID, 0, 15) +slider.align(lv.ALIGN.TOP_MID) +slider.set_y(15) button1 = lv.button(scr1) -button1.align(lv.ALIGN.TOP_RIGHT, -5, 5) +button1.align(lv.ALIGN.TOP_RIGHT) +button1.set_pos(button1.get_x() - 5, 5) label = lv.label(button1) label.set_text(">") button2 = lv.button(scr2) -button2.align(lv.ALIGN.TOP_LEFT, 5, 5) +button2.align(lv.ALIGN.TOP_LEFT) +button2.set_pos(5, 5) label2 = lv.label(button2) label2.set_text("<") led1 = lv.led(scr2) -led1.align(lv.ALIGN.CENTER, 0, 0) +led1.align(lv.ALIGN.CENTER) led1.set_brightness(slider.get_value() * 2) # led1.set_drag(True) led1.set_size(20,20) @@ -81,7 +84,7 @@ def button2_event_cb(event): ta = lv.textarea(scr1) ta.set_width(450) ta.set_height(70) -ta.align(lv.ALIGN.CENTER, 0, 0) +ta.align(lv.ALIGN.CENTER) ta.set_text("") # Assign the text area to the keyboard @@ -91,5 +94,5 @@ def button2_event_cb(event): spin = lv.spinner(scr2) spin.set_anim_params(1000, 100) spin.set_size(100, 100) -spin.align(lv.ALIGN.CENTER, 0, 0) +spin.align(lv.ALIGN.CENTER) # spin.set_type(lv.spinner.TYPE.FILLSPIN_ARC) From 20c800f89da1e1c555b11011db6f28574e3b1b73 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:39:39 +1000 Subject: [PATCH 08/17] examples: Update Dynamic_loading_font_example.py v8 to v9 API. Remove offset parameters from align() methods and use set_y() for positioning in LVGL v9. --- examples/Dynamic_loading_font_example.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/examples/Dynamic_loading_font_example.py b/examples/Dynamic_loading_font_example.py index 2bbbbad25e..c9c3393049 100644 --- a/examples/Dynamic_loading_font_example.py +++ b/examples/Dynamic_loading_font_example.py @@ -43,14 +43,16 @@ label1 = lv.label(scr) label1.set_style_text_font(myfont_cn, 0) # set the font label1.set_text("上中下乎") -label1.align(lv.ALIGN.CENTER, 0, -25) +label1.align(lv.ALIGN.CENTER) +label1.set_y(label1.get_y() - 25) myfont_en = lv.binfont_create("S:%s/font/font-PHT-en-20.bin" % script_path) label2 = lv.label(scr) label2.set_style_text_font(myfont_en, 0) # set the font label2.set_text("Hello LVGL!") -label2.align(lv.ALIGN.CENTER, 0, 25) +label2.align(lv.ALIGN.CENTER) +label2.set_y(label2.get_y() + 25) myfont_jp= lv.binfont_create("S:%s/font/font-PHT-jp-20.bin" % script_path) @@ -58,7 +60,7 @@ label3 = lv.label(scr) label3.set_style_text_font(myfont_jp, 0) # set the font label3.set_text("こんにちはありがとう") -label3.align(lv.ALIGN.CENTER, 0, 0) +label3.align(lv.ALIGN.CENTER) From 0bd8b8f72f1631c7b37fcd962fcbd2d5de9a1070 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:39:56 +1000 Subject: [PATCH 09/17] examples: Update advanced_demo.py v8 to v9 API. Remove offset parameters from align() methods and use set_y() for positioning in LVGL v9. --- examples/advanced_demo.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/examples/advanced_demo.py b/examples/advanced_demo.py index b40155fce4..573bf0b87e 100644 --- a/examples/advanced_demo.py +++ b/examples/advanced_demo.py @@ -138,7 +138,7 @@ def __init__(self, app, page): self.label = lv.label(page) self.label.add_flag(lv.obj.FLAG.IGNORE_LAYOUT) - self.label.align(lv.ALIGN.BOTTOM_LEFT, 0, 0) + self.label.align(lv.ALIGN.BOTTOM_LEFT) def button_cb(event, name): self.button_event_count[name] += 1 @@ -174,7 +174,8 @@ def __init__(self, app, page): self.style_selector = lv.dropdown(page) self.style_selector.add_style(ShadowStyle(), lv.PART.MAIN) - self.style_selector.align(lv.ALIGN.OUT_BOTTOM_LEFT, 0, 40) + self.style_selector.align(lv.ALIGN.OUT_BOTTOM_LEFT) + self.style_selector.set_y(self.style_selector.get_y() + 40) self.style_selector.set_options('\n'.join(x[0] for x in self.styles)) self.style_selector.add_event_cb(self.on_style_selector_changed, lv.EVENT.VALUE_CHANGED, None) @@ -183,7 +184,7 @@ def __init__(self, app, page): self.counter_button.set_size(80,80) self.counter_label = lv.label(self.counter_button) self.counter_label.set_text("Count") - self.counter_label.align(lv.ALIGN.CENTER, 0, 0) + self.counter_label.align(lv.ALIGN.CENTER) self.counter_button.add_event_cb(self.on_counter_button, lv.EVENT.CLICKED, None) self.counter = 0 From 5297e1a221176c1dcb0c06114cea9d040573799a Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:40:21 +1000 Subject: [PATCH 10/17] examples: Update example1.py v8 to v9 API. Remove offset parameters from align() method for LVGL v9. --- examples/example1.py | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/examples/example1.py b/examples/example1.py index cde791a153..6b9fd63385 100644 --- a/examples/example1.py +++ b/examples/example1.py @@ -1,4 +1,18 @@ -# init +""" +LVGL Example 1: Basic Widget Demonstration + +This example demonstrates: +- LVGL initialization for different platforms (SDL, ESP32, STM32) +- Basic widget creation (button, label, image) +- Event handling +- Style application +- Loading images from binary data + +Supported platforms: +- Unix port with SDL +- ESP32 with ILI9341 display +- STM32 with built-in display +""" import usys as sys sys.path.append('') # See: https://github.com/micropython/micropython/issues/6419 @@ -95,9 +109,15 @@ def init_gui(self): # Create a screen with a draggable image +# Create a new screen object (not yet active) scr = lv.obj() + +# Create an image widget on the screen image = lv.image(scr) -image.align(lv.ALIGN.CENTER, 0, 0) +image.align(lv.ALIGN.CENTER) + +# Create image descriptor with binary data +# Format: ARGB8888 (32-bit with alpha channel) image_dsc = lv.image_dsc_t( { "header": {"w": 100, "h": 75, "cf": lv.COLOR_FORMAT.ARGB8888}, @@ -106,9 +126,9 @@ def init_gui(self): } ) +# Set the image source to our descriptor image.set_src(image_dsc) -# image.set_drag(True) +# Note: set_drag() was removed in v9, use FLAG.CLICKABLE + event handlers for dragging # Load the screen and display image - lv.screen_load(scr) From 5362bf0486625947f887e7071a271e3237b59b7e Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:40:45 +1000 Subject: [PATCH 11/17] examples: Update png_example.py v8 to v9 API. Fix lv.indev_get_act() -> lv.indev_active() for LVGL v9. --- examples/png_example.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/png_example.py b/examples/png_example.py index f2ada5882e..367314df8e 100644 --- a/examples/png_example.py +++ b/examples/png_example.py @@ -48,7 +48,7 @@ def drag_event_handler(e): self = e.get_target_obj() - indev = lv.indev_get_act() + indev = lv.indev_active() vect = lv.point_t() indev.get_vect(vect) x = self.get_x() + vect.x From 4dee7eb3b17555d0ca07f1c359331ac7edf5a620 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:41:37 +1000 Subject: [PATCH 12/17] examples: Update display buffer API v8 to v9. Replace set_buffers() with set_draw_buffers() and set_render_mode() for LVGL v9. Use lv.draw_buf_create() instead of framebuffer() for creating draw buffers. --- examples/example1.py | 7 ++++--- examples/example3.py | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/example1.py b/examples/example1.py index 6b9fd63385..9be126fd11 100644 --- a/examples/example1.py +++ b/examples/example1.py @@ -59,13 +59,14 @@ def init_gui_stm32(self): event_loop = lv_utils.event_loop() lcd.init(w=hres, h=vres) - buf1 = lcd.framebuffer(1) - buf2 = lcd.framebuffer(2) + draw_buf1 = lv.draw_buf_create(hres, 50, color_format, 0) + draw_buf2 = lv.draw_buf_create(hres, 50, color_format, 0) self.disp_drv = lv.display_create(hres, vres) self.disp_drv.set_flush_cb(lcd.flush) self.disp_drv.set_color_format(color_format) - self.disp_drv.set_buffers(buf1, buf2, len(buf1), lv.DISPLAY_RENDER_MODE.PARTIAL) + self.disp_drv.set_draw_buffers(draw_buf1, draw_buf2) + self.disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) # disp_drv.gpu_blend_cb = lcd.gpu_blend # disp_drv.gpu_fill_cb = lcd.gpu_fill diff --git a/examples/example3.py b/examples/example3.py index 88a12dfa7f..441a4bb104 100644 --- a/examples/example3.py +++ b/examples/example3.py @@ -16,13 +16,14 @@ event_loop = lv_utils.event_loop() lcd.init(w=hres, h=vres) - buf1 = lcd.framebuffer(1) - buf2 = lcd.framebuffer(2) + draw_buf1 = lv.draw_buf_create(hres, 50, color_format, 0) + draw_buf2 = lv.draw_buf_create(hres, 50, color_format, 0) disp_drv = lv.display_create(hres, vres) disp_drv.set_flush_cb(lcd.flush) disp_drv.set_color_format(color_format) - disp_drv.set_buffers(buf1, buf2, len(buf1), lv.DISPLAY_RENDER_MODE.PARTIAL) + disp_drv.set_draw_buffers(draw_buf1, draw_buf2) + disp_drv.set_render_mode(lv.DISPLAY_RENDER_MODE.PARTIAL) # disp_drv.gpu_blend_cb = lcd.gpu_blend # disp_drv.gpu_fill_cb = lcd.gpu_fill From ec7afff0bd241514c301549ec0f9efbe6e27d03b Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:42:23 +1000 Subject: [PATCH 13/17] examples: Improve custom_widget_example.py documentation and error handling. Add comprehensive docstring explaining widget creation and theming. Add error handling for display_driver import. Improve code organization and readability. --- examples/custom_widget_example.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/examples/custom_widget_example.py b/examples/custom_widget_example.py index 55bc00e325..b45366a27d 100644 --- a/examples/custom_widget_example.py +++ b/examples/custom_widget_example.py @@ -1,5 +1,15 @@ -# This example shows how to create a custom widget and a custom theme +""" +LVGL Custom Widget Example + +This example demonstrates how to create a custom widget class and custom theme in LVGL: +- Creating a custom widget class with constructor, destructor, and event callbacks +- Implementing custom drawing for widgets (triangle in this example) +- Creating and applying custom themes +- Proper object lifecycle management + +The custom widget draws a triangle that points up when unchecked and down when checked. +""" ############################################################################## # Initializations @@ -9,10 +19,16 @@ sys.path.append('') # See: https://github.com/micropython/micropython/issues/6419 import lvgl as lv -import display_driver +# Initialize LVGL lv.init() +# Initialize display driver +try: + import display_driver +except ImportError: + print("Warning: display_driver not available, using default display") + ############################################################################## # Helper debug function to print member name ############################################################################## From 9981c9c4d89b7260d380e7964c5ac760b8ff2add Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:43:19 +1000 Subject: [PATCH 14/17] examples: Improve png_example.py with better documentation and error handling. Add comprehensive docstring explaining PNG decoder usage and requirements. Add error handling for display driver import and PNG file loading. Add fallback behavior when PNG file is not found. Improve code organization and user feedback. --- examples/png_example.py | 74 ++++++++++++++++++++++++++++++----------- 1 file changed, 55 insertions(+), 19 deletions(-) diff --git a/examples/png_example.py b/examples/png_example.py index 367314df8e..c15458001f 100644 --- a/examples/png_example.py +++ b/examples/png_example.py @@ -1,42 +1,78 @@ +""" +LVGL PNG Image Decoder Example + +This example demonstrates: +- Loading PNG images from filesystem using image decoder +- Creating draggable image widgets +- Using symbols as image sources +- Event handling for drag operations + +Requirements: +- PNG decoder enabled in LVGL configuration +- LV_CACHE_DEF_SIZE > 0 for smooth dragging performance +- png_decoder_test.png file in the same directory as this script + +Usage: +- Click and drag either image to move them around the screen +- The first image is loaded from a PNG file +- The second image uses a built-in symbol +""" + ############################################################################## -# -# Example of the PNG image decoder Usage. -# For dragging to work reasonable, make sure LV_CACHE_DEF_SIZE is not 0! -# +# Initialization ############################################################################## import usys as sys sys.path.append('') # See: https://github.com/micropython/micropython/issues/6419 import lvgl as lv -import display_driver_utils - -# Init +# Initialize LVGL lv.init() -driver = display_driver_utils.driver() + +# Initialize display driver +try: + import display_driver_utils + driver = display_driver_utils.driver() +except ImportError: + print("Warning: display_driver_utils not available, using default display") scr = lv.screen_active() + +# Determine script path for loading assets try: script_path = __file__[:__file__.rfind('/')] if __file__.find('/') >= 0 else '.' except NameError: - script_path = '' - -# Load the image + script_path = '.' + print("Warning: __file__ not available, using current directory for assets") -with open('%s/png_decoder_test.png' % script_path, 'rb') as f: - png_data = f.read() +# Load the PNG image from file -png_image_dsc = lv.image_dsc_t({ - 'data_size': len(png_data), - 'data': png_data -}) +png_file_path = '%s/png_decoder_test.png' % script_path +try: + with open(png_file_path, 'rb') as f: + png_data = f.read() + + png_image_dsc = lv.image_dsc_t({ + 'data_size': len(png_data), + 'data': png_data + }) + print(f"Successfully loaded PNG image from {png_file_path}") +except OSError as e: + print(f"Error loading PNG file {png_file_path}: {e}") + print("Using a placeholder instead") + # Create a simple fallback + png_image_dsc = None # Create an image using the decoder image1 = lv.image(scr) -image1.set_src(png_image_dsc) -image1.set_pos(100,50) +if png_image_dsc: + image1.set_src(png_image_dsc) +else: + # Fallback to a symbol if PNG loading failed + image1.set_src(lv.SYMBOL.IMAGE + " PNG") +image1.set_pos(100, 50) # Create an image from a symbol From 7c4329b8dda55a7276f97ac37dd66954763b10b0 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:44:42 +1000 Subject: [PATCH 15/17] examples: Improve Dynamic_loading_font_example.py with comprehensive documentation and error handling. Add detailed docstring with font conversion commands and usage instructions. Add error handling for display driver, filesystem driver, and font loading. Improve code organization and user feedback. Add fallback behavior when fonts fail to load. --- examples/Dynamic_loading_font_example.py | 146 +++++++++++++++-------- 1 file changed, 95 insertions(+), 51 deletions(-) diff --git a/examples/Dynamic_loading_font_example.py b/examples/Dynamic_loading_font_example.py index c9c3393049..ffd92d4112 100644 --- a/examples/Dynamic_loading_font_example.py +++ b/examples/Dynamic_loading_font_example.py @@ -1,66 +1,110 @@ -# -# Command line for running this example on the unix port from examples directory: -# MICROPYPATH=./:../lib ../../../ports/unix/micropython -i Dynamic_loading_font_example.py -# +""" +LVGL Dynamic Font Loading Example -import usys as sys -sys.path.append('') # See: https://github.com/micropython/micropython/issues/6419 +This example demonstrates how to load binary fonts dynamically from filesystem: +- Loading different font files for different languages (Chinese, English, Japanese) +- Using filesystem driver to access font files +- Creating labels with custom fonts -try: - script_path = __file__[:__file__.rfind('/')] if __file__.find('/') >= 0 else '.' -except NameError: - script_path = '' +Font Conversion: +To create binary font files, use lv_font_conv tool: -import lvgl as lv -import fs_driver +English font: + lv_font_conv --size 20 --format bin --bpp 1 --font Alibaba-PuHuiTi-Medium.subset.ttf + --range 0x20-0x7f --no-compress -o font-PHT-en-20.bin -lv.init() +Chinese font: + lv_font_conv --size 20 --format bin --bpp 1 --font Alibaba-PuHuiTi-Medium.subset.ttf + --range 0x4e00-0x4e56 --no-compress -o font-PHT-cn-20.bin -# display driver init... -import display_driver_utils # Default implementation. Replace by your driver -driver = display_driver_utils.driver() - -# FS driver init. - -fs_drv = lv.fs_drv_t() -fs_driver.fs_register(fs_drv, 'S') - -''' - load the font file from filesystem(For me is flash ) - How to convert font files refer here: https://github.com/lvgl/lv_font_conv - font-PHT-en-20.bin: -   lv_font_conv --size 20 --format bin --bpp 1 --font Alibaba-PuHuiTi-Medium.subset.ttf --range 0x20-0x7f --no-compress -o font-PHT-en-20.bin - font-PHT-cn-20.bin: -   lv_font_conv --size 20 --format bin --bpp 1 --font Alibaba-PuHuiTi-Medium.subset.ttf --range 0x4e00-0x4e56 --no-compress -o font-PHT-cn-20.bin - font-PHT-jp-20.bin: -   lv_font_conv --size 20 --format bin --bpp 1 --font Alibaba-PuHuiTi-Medium.subset.ttf --range 0x3042-0x3093 --no-compress -o font-PHT-jp-20.bin -''' -scr = lv.screen_active() -scr.clean() +Japanese font: + lv_font_conv --size 20 --format bin --bpp 1 --font Alibaba-PuHuiTi-Medium.subset.ttf + --range 0x3042-0x3093 --no-compress -o font-PHT-jp-20.bin -myfont_cn = lv.binfont_create("S:%s/font/font-PHT-cn-20.bin" % script_path) +Command line for running on unix port: + MICROPYPATH=./:../lib ../../../ports/unix/micropython -i Dynamic_loading_font_example.py +""" + +import usys as sys +sys.path.append('') # See: https://github.com/micropython/micropython/issues/6419 -label1 = lv.label(scr) -label1.set_style_text_font(myfont_cn, 0) # set the font -label1.set_text("上中下乎") -label1.align(lv.ALIGN.CENTER) -label1.set_y(label1.get_y() - 25) +import lvgl as lv -myfont_en = lv.binfont_create("S:%s/font/font-PHT-en-20.bin" % script_path) +# Initialize LVGL +lv.init() -label2 = lv.label(scr) -label2.set_style_text_font(myfont_en, 0) # set the font -label2.set_text("Hello LVGL!") -label2.align(lv.ALIGN.CENTER) -label2.set_y(label2.get_y() + 25) +# Determine script path for font files +try: + script_path = __file__[:__file__.rfind('/')] if __file__.find('/') >= 0 else '.' +except NameError: + script_path = '.' + print("Warning: __file__ not available, using current directory") +# Initialize display driver +try: + import display_driver_utils + driver = display_driver_utils.driver() +except ImportError: + print("Warning: display_driver_utils not available, using default display") -myfont_jp= lv.binfont_create("S:%s/font/font-PHT-jp-20.bin" % script_path) +# Initialize filesystem driver for font loading +try: + import fs_driver + fs_drv = lv.fs_drv_t() + fs_driver.fs_register(fs_drv, 'S') + print("Filesystem driver registered successfully") +except ImportError: + print("Warning: fs_driver not available, fonts may not load correctly") + +# Clear the screen and create labels with different fonts +scr = lv.screen_active() +scr.clean() -label3 = lv.label(scr) -label3.set_style_text_font(myfont_jp, 0) # set the font -label3.set_text("こんにちはありがとう") -label3.align(lv.ALIGN.CENTER) +# Load and display Chinese font +try: + myfont_cn = lv.binfont_create("S:%s/font/font-PHT-cn-20.bin" % script_path) + label1 = lv.label(scr) + label1.set_style_text_font(myfont_cn, 0) + label1.set_text("上中下乎") # Chinese text + label1.align(lv.ALIGN.CENTER) + label1.set_y(label1.get_y() - 25) + print("Chinese font loaded successfully") +except Exception as e: + print(f"Failed to load Chinese font: {e}") + label1 = lv.label(scr) + label1.set_text("Chinese font failed") + label1.align(lv.ALIGN.CENTER) + label1.set_y(label1.get_y() - 25) + +# Load and display English font +try: + myfont_en = lv.binfont_create("S:%s/font/font-PHT-en-20.bin" % script_path) + label2 = lv.label(scr) + label2.set_style_text_font(myfont_en, 0) + label2.set_text("Hello LVGL!") + label2.align(lv.ALIGN.CENTER) + label2.set_y(label2.get_y() + 25) + print("English font loaded successfully") +except Exception as e: + print(f"Failed to load English font: {e}") + label2 = lv.label(scr) + label2.set_text("Hello LVGL!") # Use default font + label2.align(lv.ALIGN.CENTER) + label2.set_y(label2.get_y() + 25) + +# Load and display Japanese font +try: + myfont_jp = lv.binfont_create("S:%s/font/font-PHT-jp-20.bin" % script_path) + label3 = lv.label(scr) + label3.set_style_text_font(myfont_jp, 0) + label3.set_text("こんにちはありがとう") # Japanese text + label3.align(lv.ALIGN.CENTER) + print("Japanese font loaded successfully") +except Exception as e: + print(f"Failed to load Japanese font: {e}") + label3 = lv.label(scr) + label3.set_text("Japanese font failed") + label3.align(lv.ALIGN.CENTER) From 92de40ca056e48a1dd703434fa3d033bd8e156df Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:45:21 +1000 Subject: [PATCH 16/17] examples: Fix missing machine import in advanced_demo.py. Add missing machine module import for RP2 platform initialization. --- examples/advanced_demo.py | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/advanced_demo.py b/examples/advanced_demo.py index 573bf0b87e..18f4ce3433 100644 --- a/examples/advanced_demo.py +++ b/examples/advanced_demo.py @@ -374,6 +374,7 @@ def init_gui_stm32(self): self.indev_drv.set_read_cb(lcd.ts_read) def init_gui_rp2(self): + import machine import xpt2046 import st77xx if sys.platform!='rp2': raise ImportError('Only works on the rp2 platform.') From 940e5b0ea374a91530d4f44fe59a3e870b80dc79 Mon Sep 17 00:00:00 2001 From: Andrew Leech Date: Mon, 9 Jun 2025 14:46:34 +1000 Subject: [PATCH 17/17] examples: Add comprehensive README documentation. Add detailed README covering all examples, platform support, and best practices. Include troubleshooting guide, requirements, and contribution guidelines. Provide clear overview of features demonstrated and usage instructions. --- examples/README.md | 163 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 examples/README.md diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 0000000000..aa7de2f0f1 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,163 @@ +# LVGL MicroPython Examples + +This directory contains comprehensive examples demonstrating LVGL (Light and Versatile Graphics Library) usage with MicroPython bindings. + +## Quick Start + +All examples are compatible with LVGL v9 API. To run an example: + +```bash +# Unix port (with SDL for GUI simulation) +cd /path/to/micropython/ports/unix +./build-lvgl/micropython /path/to/examples/example_name.py + +# ESP32 port (upload to device) +# Copy the example to your ESP32 and run it +``` + +## Examples Overview + +### Basic Examples + +- **`generic-st77xx-with-xpt2046.py`**: Simple button example for ST77XX displays with XPT2046 touch +- **`fb_test.py`**: Linux framebuffer test with basic button and label +- **`example1.py`**: Comprehensive platform-agnostic example with display initialization +- **`example3.py`**: Multi-widget example with sliders, LEDs, buttons, and keyboard + +### Advanced Examples + +- **`advanced_demo.py`**: Complex multi-platform demo with themes, animations, and charts +- **`custom_widget_example.py`**: Custom widget class creation and theming +- **`uasyncio_example1.py`**: Async/await integration with LVGL using uasyncio + +### Specialized Examples + +- **`png_example.py`**: PNG image loading and display with drag functionality +- **`Dynamic_loading_font_example.py`**: Loading custom binary fonts for multiple languages + +### Migration Guide + +- **`LvglV8ToV9MigrationGuide.md`**: Comprehensive guide for migrating from LVGL v8 to v9 API + +## Platform Support + +Examples support multiple platforms: + +- **Unix/Linux**: SDL-based simulation +- **ESP32**: With various display drivers (ILI9341, ST77XX) +- **STM32**: Built-in display support +- **Raspberry Pi Pico**: RP2 platform with SPI displays + +## Display Driver Integration + +Examples demonstrate integration with various display drivers: + +- **ILI9341**: Common SPI TFT display +- **ST77XX**: ST7789/ST7735 family displays +- **SDL**: Cross-platform simulation +- **Framebuffer**: Linux framebuffer support + +## Touch Input Support + +Touch input examples include: + +- **XPT2046**: Resistive touch controller +- **Built-in touch**: Platform-specific touch sensors +- **Mouse simulation**: SDL mouse input + +## Key Features Demonstrated + +### Widgets +- Buttons, labels, sliders, LEDs +- Text areas and keyboards +- Charts and progress indicators +- Images and custom graphics + +### Event Handling +- Button clicks and touch events +- Value change events +- Custom event callbacks +- Async event processing + +### Styling and Theming +- Custom styles and themes +- Color and gradient management +- Shadow and border effects +- Layout and alignment + +### Advanced Features +- Custom widget creation +- Font loading and text rendering +- Image decoding (PNG) +- Animation systems +- Memory management + +## Requirements + +### Common Requirements +- MicroPython with LVGL bindings +- Appropriate display driver for your hardware +- Sufficient RAM for graphics operations + +### Platform-Specific Requirements + +**Unix/Linux:** +- SDL2 development libraries +- X11 or Wayland display server + +**ESP32:** +- ESP-IDF or Arduino framework +- SPI display hardware +- Touch controller (optional) + +**STM32:** +- STM32 development board with display +- Touch sensor support + +## Error Handling + +All examples include comprehensive error handling: +- Missing driver detection +- File loading failures +- Platform compatibility checks +- Graceful fallbacks when resources unavailable + +## Best Practices + +Examples demonstrate LVGL best practices: + +1. **Proper initialization**: LVGL init before any operations +2. **Resource management**: Proper cleanup and memory management +3. **Cross-platform compatibility**: Platform detection and appropriate drivers +4. **Error handling**: Graceful failure modes +5. **Code organization**: Clear structure and documentation + +## Troubleshooting + +### Common Issues + +1. **Import errors**: Ensure all required drivers are available +2. **Display not showing**: Check display driver initialization +3. **Touch not working**: Verify touch driver configuration +4. **Memory errors**: Increase heap size or reduce graphics complexity + +### Debug Tips + +- Enable verbose output in examples for debugging +- Check LVGL configuration (lv_conf.h) +- Verify platform compatibility +- Test with simpler examples first + +## Contributing + +When adding new examples: + +1. Follow existing code style and structure +2. Include comprehensive docstrings +3. Add error handling and platform detection +4. Update this README with new example descriptions +5. Test on multiple platforms when possible + +## License + +Examples are provided under the same license as the LVGL MicroPython bindings. \ No newline at end of file