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.


    UI view inheritance - one last time

    Pythonista
    1
    1
    896
    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.
    • mikael
      mikael last edited by

      Some recent conversations prompted one last try at the topic of not being able to inherit from UI module classes. Inheritance being useful if you want to code in the object-oriented style.

      So here's a little thing to import, inheritable.py. It provides an inheritable duplicate of every UI view (and other classes).

      A silly example, a Button that changes the tint color every time you click it:

      import inheritable
      import random
          
      class TintButton(inheritable.Button):
        def __init__(self, **kwargs):
          self.super().__init__(**kwargs) # Note this
          self.action = self.set_random_tint
      
        def set_random_tint(self, sender):
          self.tint_color = tuple([random.random() for i in range(3)])
          
      btn = TintButton(title='Click me')
      

      Note the use of self.super instead of just super. This is the only 'syntactic price' we have to make for the inheritable views.

      Our btn, above, is still a ui.Button if you check its type. This has the benefit of being compatible with all other UI code, without adding any unnecessary 'container' layers to your view hierarchy.

      A slightly more useful example that adds a margin to a view, demonstrating overriding the size_to_fit method:

      class MarginView(inheritable.View):
        
        def __init__(self, margin=20):
          self.margin = margin
          
        def size_to_fit(self):
          self.super().size_to_fit()
          self.frame = self.frame.inset(-self.margin, -self.margin)
      

      Multiple inheritance works normally, with the first superclass listed taking precedence for __init__. The resulting UI type will also be that of the first superclass.

      class MultiButton(TintButton, MarginView):
        pass
        
      btn = MultiButton(flex='RTBL', tint_color='red', background_color='white', margin=50, title='Click me')
      
      print(type(btn)) == ui.Button # True
      

      (Fine detail: MarginView __init__ is not called, but margin gets set on the object anyway because of the normal ui module practice of setting any extra arguments as attributes of the instance.)

      These examples are included at the end of the file (linked at the top).

      Would be really interesting to hear if this approach works for your use case, or whether there are some surprises related to some of the UI classes.

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