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.
Slight problem with template
-
@Gadgettyke it is not about 2.7/3.5 (though you should run your code in 2.7 to make sure it works)... But some parts of
ui
were changed between pythonista2 and pythonista3. At one time, either textfield or textview did not have anaction
, and you had to use a delegate instead.I have pythonista2 still installed, if you want to share your code I could take a look.
-
that'll be great Jon,
let me try your other suggetions first then I'll have look up how to use the git again to send you the files if they don't work. I'm running it fine in 2.7 on my iPad Pro and really haven't had a problem until I tried putting it in Xcode.
Cheers
-
The easiest way to share files is to go to file library view (i.e This iPad), to the folder with your files, tap Edit, select the files, then tap the share button, and choose Gist.
Does XCode allow you to use print to print to the console? Are exception tracebacks displayed somewhere, or just fail silently?
If not, we can use NSLog statements to help figure things out. -
hi Jon
Gist coming up with error 0. am signed in ok but no joy. I have stripped most of the clutter out in another file that shows the problem nicely. its basically not calling the action textchange that's set as the action in the UI for the textfield. the colour changes were a bit of a red herring as I had another layer that changed colour not the textfield.
I have downloaded pythonista 3 again but still no joy.
can you send me an example of the app delegate solution.
here's where its going wrong
def textchange(sender): name=sender.name text=sender.text tfval[0]= name tfval[1]= text #print(name,text) # set timer 1 setval if name =='textfield1': timer1[1] = int(text) timer1[2] = timer1[1] if timer1[1] <= 1 or timer1[1] >= 1801: timer1[1] = stdtime[0] tf1 = sender.superview['textfield1'] tf1.text = str(timer1[1]) if timer1[0] == 0: label1_action = sender.superview['label1'] label1_action.text = str(timer1[1]) # set timer1 warval if name == 'textfield2': timer1[3] = int(text) if timer1[3] <= 0 or timer1[3] >= timer1[1]: timer1[3] = round(timer1[1] / 5) tf2 = sender.superview['textfield2'] tf2.text = str(timer1[3]) if timer2[0] == 0: label2_action = sender.superview['label2'] label2_action.text = str(timer2[1]) # set timer2 setval if name == 'textfield3': timer2[1] = int(text) timer2[2] = timer2[1] if timer2[1] <= 0 or timer2[1] >= 1801: timer2[1] = stdtime[1] tf3 = sender.superview['textfield3'] tf3.text = str(timer2[1]) if timer2[0] == 0: label3_action = sender.superview['label3'] label3_action.text = str(timer2[1]) #set timer2 warval if name == 'textfield4': timer2[3] = int(text) if timer2[3] <= 0 or timer2[3] >= timer2[1]: timer2[3] = round(timer2[1] / 5) tf4 = sender.superview['textfield4'] tf4.text = str(timer2[3]) if timer2[0] == 0: label4_action = sender.superview['label4'] label4_action.text = str(timer2[1]) # write back to the confer countdown display label 4 # if under warning time turn it red def label1_update(label1): label1_change = label1 label1_change.text = str(timer1[2]) if timer1[2] == timer1[3]: label1_change.text_color = '#ffffff' label1_change.background_color = '#ff0000' # write back to the pass countdown display label 5 # if under warning time turn it red def label3_update(label3): label3_change = label3 label3_change.text = str(timer2[2]) if timer2[2] == timer2[3]: label3_change.text_color = '#ffffff' label3_change.background_color = '#ff0000' # write back to label 2 def label2_update(label2): label2_change = label2 label2_change.text = str(timer1[3]) # write back to label 2 def label4_update(label4): label4_change = label4 label4_change.text = str(timer2[3]) def label5_update(label5): label5_change = label5 label5_change.text = tfval[0] def label6_update(label6): label6_change = label6 label6_change.text = tfval[1] def main(): #console.set_idle_timer_disabled(True) v = ui.load_view('main') v.background_color = sc_status[0] v.bar_color = sc_status[0] label6 = v['label6'] label5 = v['label5'] label4 = v['label4'] label3 = v['label3'] label2 = v['label2'] label1 = v['label1'] label4.font = ('markerfelt-wide', 20) label4.background_color='#ffffff' label3.font = ('markerfelt-wide', 20) label3.background_color='#ffffff' tv1 = v['textfield1'] tv2 = v['textfield2'] tv3 = v['textfield3'] tv4 = v['textfield4'] tv1.text=str(timer1[1]) tv2.text=str(timer1[3]) tv3.text=str(timer2[1]) tv4.text=str(timer2[3]) v.present('sheet') delta = time.clock() seconds[1] = int(delta) # timing loops engaged and running while True: #how_long(seconds) #if seconds[0] == 1 and (timer1[0] == 1 or timer2[0] == 1): # timer_update() # calling to update label values label1_update(label1) label2_update(label2) label3_update(label3) label4_update(label4) label5_update(label5) label6_update(label6) # seconds[0] = 0 # check if still on screen? if not then exit onscreen = v.on_screen if onscreen is False: # console.set_idle_timer_disabled(False) return False main()
runs beautifully on my iPad but it will not call textchange def from Xcode version.
Cheers
-
@Gadgettyke can you try it without the while True loop? That can cause some problems. The "right" way to do something like that is to have a thread, or at a minimum something like
def update(): #update labels here... # if onscreen: ui.delay(update, 0.1) #some suitable update rate #then in main... update() #start update
Also, your code above does not seem to complete, in the sense that i dont see
timers
defined, etc? -
actually, lets try greatly simplifying:
import ui, console def textchange(sender): console.hud_alert('textchange called {}'.format(sender.name)) class MyTextFieldDelegate (object): def textfield_should_begin_editing(self, textfield): console.hud_alert('shouldbegin called {}'.format(textfield.name)) return True def textfield_did_begin_editing(self, textfield): console.hud_alert('didbegin called {}'.format(textfield.name)) def textfield_did_end_editing(self, textfield): console.hud_alert('didend called {}'.format(textfield.name)) def textfield_should_return(self, textfield): textfield.end_editing() return True def textfield_should_change(self, textfield, range, replacement): console.hud_alert('shouldchange called {}'.format(textfield.name)) return True def textfield_did_change(self, textfield): console.hud_alert('didchange called {}'.format(textfield.name)) def main(): v=load_view('main') tv1 = v['textfield1'] tv2 = v['textfield2'] tv3 = v['textfield3'] tv4 = v['textfield4'] delegate=MyTextFieldDelegate() for tv in [tv1, tv2]: tv.action = textchange for tv in [tv3, tv4]: tv.action =None tv.delegate =delegate v.present('sheet') console.hud_alert('main complete') main()
Use this as your main script. Textfield1 and textfield2 will alert use when text change. 3 and 4 will alert you for each stage (when you start editing, when you type, and when you press enter)
If both types work, then we know the problem is elsewhere in your code, such as an exception in the callback itself, or the while True issue. If neither work, then we are back to basics.
can you confirm that textfield1, etc are TextField, and not TextView? TextViews do not (or at least didnt at one time) have action attributes, instead you had to use delegates (which are named differently)
-
hi jonB
sorry it was a much cut down listing from a much much larger program, The only problem I have is with the textfield so I isolated it for you.
the pyui file code is
] "frame" : "{{88, 104}, {145, 67}}", "class" : "TextField", "attributes" : { "uuid" : "4DA8C238-6892-48F7-8EF3-1D626569A9D0", "corner_radius" : 6, "frame" : "{{412, 368}, {200, 32}}", "border_width" : 1, "custom_attributes" : "", "alignment" : "center", "autocorrection_type" : "default", "action" : "change_time1", "text" : "120", "placeholder" : "", "font_name" : "MarkerFelt-Wide", "spellchecking_type" : "default", "class" : "TextField", "name" : "textfield1", "font_size" : 46 }, "selected" : false },
so it is selected as a textfield. the code is the same for all four fields 1,2,3,4
I'm new to python and have programmed PLC's mainly so a linear approach is something I tend to default to. not really done much with C previously.
all I can say is wow! many thanks, i'll get this into my test program and see if that cures it. if so I see a long weekend of getting into my main program.
I'll get back to you on the results.
Cheers -
Many Many thanks JonB, the class did the trick and its functioning perfectly.
I've put it in the main body of my program and its sorted out the issue fully.
the setting of the tv.action has made sure my function works a treat.
You mentioned that the while true may cause a problem, is this something you have come across before?
cheers
Gadgettyke -
i will point out that your textfield action was set to change_time1. maybe that is just because you created a simplified version?
while True will give you problems if you use ui.in_background, because it queues up those on the same thread running the while True. Probably not the problem here, but I wasnt sure if the Xcode template works differently.
-
Oops the pyui code snippet is from the full program not the simplified version I sent you. As you can tell not genius level at python unlike your good self. However i’m excellent at other things like 3D cad and printing so if ever I can repay the favour just let me know.
Ok I see what your saying, if I ever get my head round the class thing, the more I get out of the loop the better.
I do like the update suggestion as well and have included that now as well.
Cheers