Forum Archive

Getting a List of all ui GUI classes programmatically

Phuket2

I wanted to see if I could get a list/dict of all ui GUI objects programmatically. I can see I can get a list of all classes if I do something like my_list =dir(ui). In this case it's not any better than hard coding a list of objects myself, as I only want GUI objects in my_list. I would like my_list to be populated with something like ['ui.Button', 'ui.DatePicker', all the other ui GUI classes].
The reason I want this, is upon receiving a text argument, say 'ui.Button', I would like to confirm it is a valid ui object/class. I think I could do a try: , but would prefer to avoid a try: if I can do it more directly. I can see other ways to mostly get this right also, but prefer the most correct solution.
Thanks in advance

dgelessus

Since all UI elements inherit from ui.View, you could list all subclasses of that class:

import ui

ui_elements = []
for cls in vars(ui).values():
    if isinstance(cls, type) and issubclass(cls, ui.View):
        ui_elements.append(cls)

# Or as a list comprehension:
ui_elements = [cls for cls in vars(ui).values() if isinstance(cls, type) and issubclass(cls, ui.View)]
Phuket2

@dgelessus, thanks so much. However, it makes me want to cry. Not literally, but still going through growing pains learning python. I really love python, but a lot to learn. Maybe it's my learning technique, learning out of order. Also going pretty slow, only ever doing python on my iPad. No external keyboard.
I apologise, this is more a Python language question than Pythonistia question. Did not realise that until I saw your response.
Thanks again, exactly what I needed. I would never have come up with this myself. At least not now.

Phuket2

@dgelessus , I am not sure if this was broken at the time or not. But if you want a list of ui elements aka controls this includes extras you don't want. Example ui.ActivityIndicator, ui.TableViewCell
From what I can see you can't filter them our without using there names. I have also tried numerous other ways, but I can't figure out a way to isolate only the user interface controls without having to get very specific 😰
Maybe there is a way i can not see.

dgelessus

There's no way to tell from code which classes count as "interface controls" and which don't. One solution would be to use a "blacklist" as you said, you could add a condition like and cls not in (ui.ActivityIndicator, ui.TableViewCell) to do that. Or you could decide based on the name (which you can access with cls.__name__) and do something like and cls.__name__.endswith("View").

ccc

isinstance() and issubclass() also can take a tuple for the second param as in isinstance(obj, (ui.ActivityIndicator, ui.TableViewCell)).

Webmaster4o

@ccc I love these tuple arguments when they're available. I use them all the time. I wish more of the builtins had that functionality, honestly, things like

replace(('Cats','Dogs'),'Animals')

would be really useful.

JonB

@Phuket2
I can understand not wanting to include TableViewCell... but activityindicator seems like like a perfectly valid element. It can be added as a subview, etc.

try is very pythonic... it would also let you support custom ui elements that you don't know about yet.

Phuket2

Ok, thanks guys. Interesting about the activity indicator. I have to take a breath and read about it. It's the 2 nd time something useful has popped up about that.
Well at least I know I was doing as much as I could now. I thought a good chance I was missing something

ccc

@Webmaster4o your .replace() takes a tuple idea is brilliant. (RTT has a nice ring to it.) You should propose it as a change to the Python Standard Library. In my book it is a great idea that would be broadly applicable. The Python community is looking for improvements that push developers to adopt Python 3 over Python 2 and this kind of improvement might fall nicely into that category. It would be fun to find out who the youngest PEP author is.... Maybe you could even break a record while contributing to core Python.

Phuket2

I am not sure what you think about the below pattern to get a list of ui controls in a list comp (I hope I am not embarrassing myself again 😱). I still struggled with it. I used vars(ui).values() instead of playing with dir. I can see the vars way returns a lot of data to iterate through. But it looks the most conise way to me.
But I did many variations. Start to get a brain freeze after a while. I kept in ActivityIndicator, but still appreciate the comments about passing tuples to issublass for example. I didn't know about that. Well, I don't know most. But I did try the notation, worked as advertised.

import ui

x = [cls for cls in vars(ui).values() if hasattr(cls, 'alpha') and not issubclass(cls, ui.TableViewCell)]
print x, len(x)
dgelessus

@ccc I doubt a PEP would be necessary for this. @Webmaster4o The idea sounds good though.

Phuket2

@dgelessus , oops sorry I now see where I got the vars.values() from. I thought I had found it in stackflow. Sorry, you give the complete answer already. I must have seen it last night and it stayed in my head. It still took me a while to get to your solution today 😂😂 sorry, I really didn't mean to plagiarize you. But I just realised I did.

Edit. Was a BLE (BlackLabelError) I think there should be a PEP for that 🤕