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.
Delegate example
-
I wanted to make a minimalist example of a working delegate to help me understand them. Please look at my example below and show me how to make this example work.
import ui tv = ui.TextView() tv.present() class MyTextViewDelegate (object): def textview_did_begin_editing(self, tv): tv.text = 'it worked'
-
There's basically just one thing missing in your code: You have to create an instance of your delegate class, and then assign it to the
delegate
attribute of the text view:import ui class MyTextViewDelegate (object): def textview_did_begin_editing(self, tv): tv.text = 'it worked' tv = ui.TextView() tv.delegate = MyTextViewDelegate() tv.present()
-
What if tv was created in a method/function? What is a proper way to access it in a class, especially cause the class is always in the main thread(I believe)? Do I make tv global?
Global seems like the wrong way to do it...
For example will the code below work?:
import ui class MyTextViewDelegate (object): def textview_did_begin_editing(self, tv): tv.text = 'it worked' def update(sender): tv = ui.TextView() tv.delegate = MyTextViewDelegate() tv.present()
-
The variable passed to the delegate method is all handled for you -- the thread handling ui events sees that you are trying to edit the textview, and calls the textview's delegate method, with the TextView object as the argument. So the fact that you used
tv
as the name in both places makes no difference -- you could have twenty textview's on a page all set to the same delegate instance.I'm not sure if your specific example would work, if
update
is a Buttonaction
for example -- mostly because I'm not sure if you can call present from within a callback like that. You might need@in_background
or aui.delay
. Generally, I'd recommend against presenting a new view from within anaction
, except forpopover
s. Another option is to have one root view, and replace out the subviews if you want to change what is presented.Note also that once you present a textview like this (created/presented inside a method), you have no access to that textview anymore except from its delegate methods. That's probably ok.
A common pattern you will see, is that people will make their delegate class the same as their custom View class, then any "shortcut" variables to the various components of the ui can be attributes of your custom class. This keeps things out of the global namespace where they can be accidentally overwritten, but still lets you have easy access to key parts of the ui, without having to traverse the hierarchy in your delegate methods (e.g. you can use
self.textview1
instead oftv.superview.superview['panel']['textview1']
)Here's a simple example with two components on a custom root view. Both components are created entirely within the class init method, but are easily accessible (as instance attributes) from the other class methods.
import ui def MyView(ui.View): def __init__(self): self.width, self.height = ui.get_screen_size() self.tv = ui.TextView(frame=(10,10,400,400)) self.tv.delegate = self self.but = ui.Button(title='Submit', frame=(10,420,100,100), bg_color='red') self.but.enabled = False self.but.action = self.button_action self.add_subview(self.tv) self.add_subview(self.but) def textview_did_change(self,tv): if tv.text: self.but.enabled = True def button_action(self, sender): console.hud_alert('Message sent') self.tv.text = '' sender.enabled = False v = MyView() v.present()
-
Thank you for the explanation and your time. I think I get it.
By the way, I tried to run your example and it had an error...