Obj.get_selected_str return type

Not sure what I’m doing wrong but it seems like some objects like ldrop down list or roller do not return a string with the get_selected_str method?

I don’t get the expected behavior when either doing a string compare or typecasting to an int.

test code:

import lvgl as lv
from ili9XXX import ili9341
from xpt2046 import xpt2046

# Initialize drivers
lv.init()
ili9341()
xpt2046()


# Simple Roller
def event_handler(obj, event):
    if event == lv.EVENT.VALUE_CHANGED:
        option = " "*20
        obj.get_selected_str(option, len(option))
        option_string = option.rstrip()
        print(type(option_string))
        option_string = str(option_string)
        #option_string = ''.join([chr(b) for b in option_string])
        option_int = int(option_string)

        print("Selected number: |%s|" % option_string)
        if option_string == "22":
            print("found string: %s" % option_string)

roller1 = lv.roller(lv.scr_act())
roller1.set_options("\n".join([
                    "1",
                    "22",
                    "333",
                    "4444",
                    "55555",
                    "666666",
                    "7777777",
                    "88888888",
                    "999999999",
                    ]), lv.roller.MODE.INIFINITE)

roller1.set_visible_row_count(4)
roller1.align(None, lv.ALIGN.CENTER, 0, 0)
roller1.set_event_cb(event_handler)

embeddedt note: simulator link

Error:

>>> import roller
ILI9341 initialization completed
Enable backlight
Double buffer
>>> <class 'str'>
Traceback (most recent call last):
  File "roller.py", line 21, in event_handler
ValueError: invalid syntax for integer with base 10

I’m sure I’m missing something :slight_smile:

Hi @saul !

get_selected_str actually copies bytes, including the null-termination of the string.
If you check out option_string you’ll find out it’s '22\x00' and not '22', for example.

The correct way to handle this is to provide get_selected_str a bytearray, decode this bytearray to string and strip the trailing null termination:

        option = bytearray(20)
        obj.get_selected_str(option, len(option))
        option_string = option.decode("utf-8").rstrip('\0')

Link to simulator

Thank you for reply Amirgon I really appreciate it.

I updated the the event handler:

    if event == lv.EVENT.VALUE_CHANGED:
        option = bytearray(20)
        obj.get_selected_str(option, len(option))             << Line 16
        option_string = option.decode("utf-8").rstrip('\0')

        #option_string = ''.join([chr(b) for b in option_string])
        option_int = int(option_string)

        if option_string == "22":
            print("found string: %s" % option_string)

        if option_int == 333:
            print("found int: %d" % option_int)

This is the error I’m getting now:

>>> import roller
ILI9341 initialization completed
Enable backlight
Double buffer
>>> Traceback (most recent call last):
  File "roller.py", line 16, in event_handler
TypeError: can't convert 'bytearray' object to str implicitly

If I leave option as:

    if event == lv.EVENT.VALUE_CHANGED:
        option = " "*20
        obj.get_selected_str(option, len(option))
        option_string = option.decode("utf-8").rstrip('\0')    << Line 17

I get:

>>> import roller
ILI9341 initialization completed
Enable backlight
Double buffer
>>> Traceback (most recent call last):
  File "roller.py", line 17, in event_handler
AttributeError: 'str' object has no attribute 'decode'

That’s strange, because it is working for me on the simulator (link)

Are you using an up-to-date version of lv_micropython?
Are you able to reproduce this on the online simulator?

I compiled from the lv_miropython repo:

The firmware I’m using was complied back in 09/23/2020 when they had lvgl 7 bindings.

I’m working on compiling from the latest git build which has lvgl 8 bindings, but I’m still working through some issues there as the build process has changed from the last time I compiled it.

Maybe its not worth working this out on such an old build :slight_smile: I can just open a new conversation if I have the same issue with the latest build.

Latest v7 is available on GitHub on GitHub - lvgl/lv_micropython at release/v7

Of course, it you can, it’s best to use the latest v8 on master branch.

Thanks again Amirgon!!

I was able to compile the latest version version of lv_micropything which I think has the 8.1 bindings and now the following example is working:

# Simple Roller
def event_handler(e):
    code = e.get_code()
    obj = e.get_target()
    if code == lv.EVENT.VALUE_CHANGED:
        option = bytearray(20)
        obj.get_selected_str(option, len(option))
        option_string = option.decode("utf-8").rstrip('\0')

        #option_string = ''.join([chr(b) for b in option_string])
        option_int = int(option_string)

        if option_string == "22":
            print("found string: %s" % option_string)

        if option_int == 333:
            print("found int: %d" % option_int)


roller1 = lv.roller(lv.scr_act())
roller1.set_options("\n".join([
                    "1",
                    "22",
                    "333",
                    "4444",
                    "55555",
                    "666666",
                    "7777777",
                    "88888888",
                    "999999999"
                    ]), lv.roller.MODE.INFINITE)

roller1.set_visible_row_count(4)
roller1.align(lv.ALIGN.CENTER, 0, 0)
roller1.add_event_cb(event_handler, lv.EVENT.ALL, None)

output:

>>> found string: 22
found int: 333

There must have been some issue with either the micropython or lvgl version I previously compiled