How to better structure a complicated LVGL Project?

I’ve been working on a (for my skills) relatively complex lvgl project. It’s similar to the lv_printer_demo, and currently the GUI is about 2000 code lines long with about 12 Screens.

The default lvgl template only separates between static/global variables and functions, but right now my screens are getting really complicated and my project is turning into spaghetti code.

Would someone please point me to a cleanly structured LVGL Project?

1 Like

I think this is a pretty good question - i’ve been fighting with it too.

After a few times thru, I’m going with this -
assets (images) go into one folder
“screens” (full screen structures) go into a screens folder
views (reusable components like buttons) go into a 3rd folder.

What I’m debating internally is… if I want to instantiate all screens (say 6-10 screens) at application start, and show the screen without having to “rebuild” it every time it needs to be displayed, or build screens on demand.

I’m currently doing the former, where I created a struct that holds the screen lv_obj_t along with a callback function that gets hit on screen is displayed - so the screen can rebuild only the things that need refreshing every time it’s viewed.

That sounds as a good candidate for a class. :wink:

I defined a base class with abstracted screen hooks and then a sub-class for each screen.

The screen coordinated is done by a central screen manager which uses an enum with a value for each screen and gets requests to switch screens.

This makes the screen decoupled from each other and the policy of instantiating a screen on demand or on initialization is left to the screen manager.

For the individual UI elements, I am using a central file with abstractions and functions for the UI elements I use. This provides code sharing and keep the LCGL details mostly in one place.

E.g.

Hope it helps.

I’ve also considered doing something similar, but since I’m limited to C in my project, the implementation wouldn’t be as clean (or at least it would be more susceptible to bugs since C isn’t inherently meant for object oriented programming)

Yeah I also considered rendering all screens in the background and then just flipping between them and even tried that for a bit, but then changed to “building” each screen during runtime.

It definitely made programming easier since I don’t always have to pass the pointer to the screen objects I’m currently rendering and instead use lv_scr_act() knowing that the drawing functions will only get called when the screen content is meant to be displayed.