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 do I access a gui element?
-
I've read the ui guide but I haven't found a solution to my problem.
Given my pyui in my_gui.pyui:
http://i.imgur.com/cPlQddh.pngHow can I access the ui elements in my separate my_ui.py file?
For example, I want pressing the 'Small' button to set the text of the text field to 'this is small'.
Right now I cannot make the button make changes to the text field element.import ui import imgtagr import clipboard def small_tapped(sender): sender.title = 'cool' def medium_tapped(sender): pass def large_tapped(sender): pass def none_tapped(sender): pass def main(): ui.load_view('my_gui').present('sheet') main()
-
there are some good tutorials over at pythonista-tools github repo.
But basically your options are:
sender.superview['textfield1']
or, storing global references to ui elements you want, or custom view with references stored in self.
-
Hi @pyfonista,
I am a beginner myself, but hope this helps.
Note your my_gui.pyui file should have 3 buttons with their action as, small_tapped, medium_tapped and large_tapped. Also you must have a textfield1 to print the status of which button is pressed.import ui def small_tapped(sender): sender.superview['textfield1'].text= 'Small' def medium_tapped(sender): sender.superview['textfield1'].text= 'Medium' def large_tapped(sender): sender.superview['textfield1'].text= 'Large' def main(): ui.load_view('my_gui').present('sheet') main()
-
All the above looks correct. But why not start at the begining.
ui.load_view('my_gui').present('sheet') - I don't use this pattern
I use -v = ui.load('my_gui') # then can access the subviews as subscripts v['textfield1'].text = 'Whatever I want' v.present(style='sheet')
I hope this makes sense.
v = ui.load_view('my_gui').present('sheet')
v will not work as expected. -
Totally Agree With @Phuket2 ..
In Fact, I Do Not Even Use .pyui Files Anymore 🙏🏽👍🏽🙏🏽 -
@ramvee , not sure you are aware of the below or not. The PYUILoader was built up by @Jonb after some questions on the forums here. Basically it allows a loaded UIFile to look and act as a custom class. Not just a wrapper. If you do a search in the forum you will come up with quite a bit about it. As far as I know, the below is the most refined version. As it handles custom properties set in the pyui file also. Honestly, its worth a look. I have gone backwards and forwards on using UIFiles. I think were i will end up falling is that for very quick and dirty things as well as examples etc, i will not bother. But once I start to make something someone might possibly use other than me, then I think I should UIFiles. Several of the guys here that really know what they are doing have expressed their views on the complexity of maintaining ui.Views that start to get a little complex, using flex etc. Anyway, each to their own.
Hope the below is helpful to someone.import ui class PYUILoader(ui.View): # this acts as a normal Custom ui.View class # the root view of the class is the pyui file read in def WrapInstance(obj): class Wrapper(obj.__class__): def __new__(cls): return obj return Wrapper def __init__(self, pyui_fn, *args, **kwargs): bindings = globals().copy() bindings[self.__class__.__name__] = self.WrapInstance() ui.load_view(pyui_fn, bindings) # call after so our kwargs modify attrs super().__init__(*args, **kwargs) class MyClass(PYUILoader): ''' Just have to be mindful of a few things. 1. Set your instance vars before the super is called, otherwise they will not be accessible in the did_load. 2. Do any form element setup in the did_load call back. The ui module call this method. 3. In the in the UIFile in the 'Custom View Class' section you must put in the name of this class. In this case MyClass 4. I like the dict update in the did_load method. Nothing to do with getting this class setup. But its just a quick short cut for setting instance vars to your form elms for you can access them with dot notation. of course you could have just done self.label1 = self['lablel1']. Just a nice short cut. ''' def __init__(self, uifilename, *args, **kwargs): self.set_instance_vars_here = 'Yes you got me' super().__init__(uifilename, *args, **kwargs) def did_load(self): print(self.set_instance_vars_here) # add all instance vars for the form elements to the class. # its ok, but the late binding means the editor can not help # still better than string indexs I think. # This is not recursive. It could be though. [self.__dict__.update({sv.name: sv}) for sv in self.subviews] self['label1'].text = 'My Text' self.label1.text = 'My Text' if __name__ == '__main__': uifilename = 'test1.pyui' f = (0, 0, 300, 400) v = MyClass(uifilename, frame=f) v.present(style='sheet', animated=False)
-
@omz as a side note. It seems to me that this functionality should be built into Pythonista. When you are learning this stuff all seems like black magic and work around for things that's should not be done.
Something built in and done elegantly and documented, I think could position UIFiles more in the Pythonista Eco system to where they should be. I think people really struggle over whether to use them or not only because of a few issues.
Again, i know only so many hours in the day. I just think if this was considered part of the normal work flow and backed up with documentation, I don't think people would agonise over the options so much. It would start to become clearer what is best for their needs.
Anyway, my thoughts for today.
Pls remember, its been around 36hrs since I have had a real cigarette :) I feel strange -
@Phuket2,
Thank you for the info, will try and understand what this is about!
Admire you for your helping nature!
Namaste!