omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    How to set action attribute in UI editor to a class-method handler rather than a function?

    Pythonista
    3
    6
    3776
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • ltddev
      ltddev last edited by

      How do I set the action attribute in the UI designer to a object handler method rather than a function? I see how to set the action attribute of a view such as Button to a function such as 'button_tapped' in code outside of the UI Designer, but I want to both use the UI editor AND code in a object oriented fashion. I therefore want to associate my handler METHOD to the action attribute. In code it is simple - you create an instance of your handler class that contains the handler method and then you bind the Button view's action attribute to that instance.method.

      But is is possible to set this in the UI editor, which nicely separates interface from implementation, given that in code its the actual instance name you are setting as in myButton.action = anInstancePreviouslyJustCreated.method? I tried playing with creating the instance of the handler class at different points in the code but no matter what I try I can not get the handler method to be called. What would the value in the UI editor be exactly for the action attribute?

      1 Reply Last reply Reply Quote 0
      • dgelessus
        dgelessus last edited by

        Not sure if and how methods can be set as actions from the UI editor, but you could set the method in code after loading the view:

        import ui
        
        class ActionClass(object):
            def action_method(self, sender):
                sender.title = "I got tapped!"
        
        handler = ActionClass()
        root = ui.load_view()
        root["button1"].action = handler.action_method
        root.present()
        

        It's just one line of code and to me doesn't look as bad as you seem to describe it ;) Have you tried storing the method in a global name before loading the view? That might work, but would not be very clean code...

        1 Reply Last reply Reply Quote 0
        • ltddev
          ltddev last edited by

          @dgelessus,

          Thanks. It's not as nice and abstract as it would be tucked away in the pyui file but it is at least a workaround if the goal is to use the ui editor for all ui construction and an OO-style of coding in the implementation script. I agree with you that it is likely not possible since you need a live instance of the implementation when you make the association.

          1 Reply Last reply Reply Quote 0
          • omz
            omz last edited by

            The only way you can do this at the moment is to have the object that defines the action methods also load the view, e.g. in the initializer. In the following example, the action in your pyui file would be set as self.action_method:

            import ui
            
            class MyViewController (object):
              def __init__(self):
                self.view = ui.load_view()
                
              def action_method(self, sender):
                sender.title = 'tapped'
            
            vc = MyViewController()
            vc.view.present()
            
            1 Reply Last reply Reply Quote 0
            • ltddev
              ltddev last edited by

              I think that, given I prefer to use OO and classes/objects to implement the code behind the widgets, this is not actually a limitation but a role that makes sense anyway for this object.

              @omz, when you say that "The only way you can do this at the moment..." are you saying that this is a restriction? Like I say, the way I see it, it makes sense as the preferred way to load the view anyway.

              1 Reply Last reply Reply Quote 0
              • omz
                omz last edited by

                when you say that "The only way you can do this at the moment..." are you saying that this is a restriction? Like I say, the way I see it, it makes sense as the preferred way to load the view anyway.

                It definitely makes sense to load the view this way, and that's why it's one of the two supported methods of assigning actions.

                To be honest though, if I'd write the load_view function again today, I would probably add an explicit 'owner' parameter, as that would be more pythonic in my opinion.

                When you think about how you might write a load_view function in pure Python, it becomes clear that it has to do quite a bit of "magic" you might not expect. Normally, when you call a function from a method, that function has no idea what self refers to, because it's just a local variable (parameter) in the scope of your method.

                So the load_view function basically has to look at the stack to determine what self refers to in the context of your call. This is of course possible to do in Python, but it's a little ugly and goes against the "explicit is better than implicit" principle.

                1 Reply Last reply Reply Quote 0
                • First post
                  Last post
                Powered by NodeBB Forums | Contributors