I am working on some micropython based GUI design and I have come accross some very strange peculiarities with unexpected behaviour.
What MCU/Processor/Board and compiler are you using?
I have tested using the unix port of lv_micropython as well as the online simulator
What do you want to achieve?
I am trying to use the width of an object to set the size of another, however whenever I try to get the width of an object I get a size of 0. The only exception to this appears to be for the base lv.obj() with no parent which is showing the full screen width.
This can be seen by toggling commenting on lines 21/22 to show the set width works, and by toggling commenting on lines 152/153 to change the parent object.
align vs align_to
I have two sub objects in my scr object (which is a child of another base lv.obj()). If I align the first object using top_bar.align(), the second object disappears. If, however, I use top_bar.align_to() the second object now appears. The two objects shouls be in no way linked. This effect can be tested by toggling commenting on lines 23/24.
Object size (and position) is set according to the layout.
Usually, you are not supposed to read size and position of one object and set the size and position of another. Instead you should select and configure your layout. See the Flex layout documentation for example.
The reason you are getting 0 is probably because the screen was not “layed out” yet. You cannot expect sizes and positions to be set right after you create some objects.
Here is an example where a simple button is created. At the beginning its width is 0, only at later stage it gets the right dimensions.
Not sure about the details, probably also related to layout.
Please try Flex or Grid layout to position your objects.
I understand that this may partly be due to being drawn directly from a c library, but this seems very unintuitive from a python point of view.
I am currently not specifying any kind of layout, but what I am doing is specifying the size (I have tried both with set_size, and set_width & set_height). I would expect that these would provide values that could be read outside the object by using the appropriate get function.
I believe you need to run obj.update_layout() on an object before getting its width. This is because set_width updates the object’s internal width property, but does not cause the object’s bounding box to be recalculated immediately, for performance reasons.
get_width is just using the bounding box, not the style property, so it returns the default value of 0, since the bounding box isn’t recalculated till the object is drawn for the first time.
The behavior is slightly unintuitive, but the feature was necessary to avoid lag issues like this.
I updated your example with some update_layout calls; it may have fixed your problem.
Out of interest I have just looked throuhg the code in that file and there id quie a difference between align, and align_to. I’m assuming there are reasons for this, but align seems like it should be a specific case of align_to with base=obj.parent, is there a reason that this isnt the case?
It might cause problems in some cases. E.g. if flexbox calls get_width but it triggers layout refresh, it will call flexbox calculation again, which calls get_width which causes layout refresh… infinite cycle. Now there is a mutex in lv_obj_update_layout to prevent nested calls, but it’d be better to use it only for error detection.
Probably these can be avoided with careful design in layouts, i.e. use lv_area_get_width(&obj->corrds) instead.
Regardless of this, the performance drop should be negligible but it should be measured with the widget demo (I consider it as a typical UI).