Forum Archive

Access a Subview Element (.pyui)

AlejandroDDD

So, I’m trying to access a subview element located in a custom view made in a .pyui
I saw another post where they suggested to use...

a = sender.superview['view1']['subview']

And it worked, I used it for assigning an image to the imageview and changing the alpha of the whole custom view when a button is tapped:

def example(sender):
    def animation1():
        #Here I “call” the subview element in the custom view
        d = sender.superview['view1']['image']
        z = ui.Image.named('image01.PNG')
        d.image = z
        #Here I access only to the custom view
        view1 = sender.superview['view1']
        view1.alpha = 1

ui.animate(animation1, duration=2)

Later in the same script I want to acces a Label and a button in another custom view and then change the Text and title when the button is tapped. I used the same structure of the first example but it still doesn’t work:

def example(sender):
    def animation1():
        d = sender.superview['view2']['bFac']
        d.title = 'Example Title'
        bla bla, more text

ui.animate(animation1,duration=2)

When I run the program I get the error TypeError: 'NoneType' object is not subscriptable

I don’t know if I’m making understand my self Xd, I’m new in Pythonista, hopping someone can answer me.

caddtec

I there! Actually, it is pretty simple. Just access the ‘text’ attribute of the ‘title’ element.

Cheers!
D

AlejandroDDD

Same thing happened, It popped the NoneType error.

caddtec

I may have answered a little fast. It seems like your label does not get initialized (since the NoneType)... I expect it is the bFac element that is not initialized but it could be that it just does not exist. Is the sender the button? If so, maybe the bFac object is not in the super view. Try printing the keys to the superview[‘view2’] to see if the bFac element is there.

cvp

@AlejandroDDD I think that sender.superview['view2'] does not exist and then is not subscriptable

AlejandroDDD

@cvp your right, i was trying and it doesn’t call even the ‘view1’, but only happens now, I didn’t had that problem in the past function (the one of the example), so what am I doing wrong?
Thanks to both of you by the way.

JonB

As a way if debugging, print sender.superview.name to make sure you are in the view you think. Also

for v in sender.superview.subviews:
     print (v.name)

That list will be the names you can index using sender.superview[name]

You can repeat with the named view to see it's subviews' names.

AlejandroDDD

I was thinking and maybe for getting out of the subview and running the other one, idk, but I thing the custom view with the subviews act like an independent ui.view()
Maybe use something like:

sender.superview.close()

Am I right? (I tried it didn’t work)

JonB

Ok, let's start very basic.

Your views start at the root view -- the one you call present on -- and then are heirarchical going down . If you assign a name in the UI editor, you can refer to a subview by name, a but only from it's immediate superview.

Please do the following:. From your button action, call this method on sender.

def print_view(sender):
    root=sender
    while root.superview:
        root=root.superview
    print('root:', root.name, type(root))
    def print_subviews(v, prefix):
        print(prefix, v.name, type(v))
        for sv in v.subviews:
            print_subviews(v, prefix+'+')
    print_subviews(root,'')

That will print something like
root UI.View
+view1 UI.view
++button1 ui.Button
++textview1 UI.Textview
+label1 UI.LabelView

Etc. Hopefully this helps explain your view heirarchy.

Note that often people create global variables, or attributes in the root view that point to deep subviews...

root=ui.load_view (....)
root.input_box=root['view1']['textview1']
....

Then you can simply refer to these in your callbacks functions without having to use superview/subview business in your callbacks. If your button takes action on a specific item, that ends up being cleaner. If instead you have 5 buttons using the same action, then you would use sender. Superview