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.
App crashes on a long running button action
-
I tried debug this code, and it worked correctly, but after I running this one, the whole app crushed.
def start(sender): def ani_pause(): sender.image = ui.Image.named('iob:pause_32') def ani_play(): sender.image = ui.Image.named('iob:play_32') global is_playing if is_playing is False: ui.animate(ani_pause) is_playing = True start_time = time.time() label = sender.superview['label1'] label2 = sender.superview['label2'] time_left = 0 while int(label.text) != 131: time.sleep(0.01) time_now = time.time() duration = time_now - start_time time_left += 1 label2.text = str(10 - time_left) if label2.text is '0': label.text = str(int(label.text) + 1) time_left = 361 ui.animate(ani_play) is_playing = False else: is_playing = False ui.animate(ani_play)
-
it seems like I can’t put a whole loop into button action, but I want to do a counter by time function.
-
@ZinoSama said
if label2.text is '0':
Please read this
Python is operator compares two variables and returns True if they reference the same object.
If the two variables reference different objects, the is operator returns False .
In other words, the is operator compares the identity of two variables and returns True if they reference the same object.Thus, your if is always False, thus infinite loop. Use
if label2.text == '0':
But, anyway, your code is still an infinite loop. Is that normal that you test versus 131 and set 361?
Please put some prints to debug your problem and follow the values of your variables, likelabel2.text = str(10 - time_left) print(time_left, label2.text) if label2.text == '0':
-
@cvp the 361 one is the value I forget to change for testing.
I wrote a simple while loop to test button action. The result is the label will only show 10 after 10 seconds, but not get from 1 to 10 by each second. it just didn't show 1 to 9def start2(sender): label = sender.superview['label1'] num = 0 while num != 10: time.sleep(1) num += 1 label.text = str(num)
-
Button actions stop the entire display thread until the function exits, unless you use @in_background
Solution:. Wrap your function with the in_background decorator. Note however that only one in_background gets executed at a time, in order.
-
+1 @JonB Ideally, actions should be super simple and run quickly. Move complexity to other parts of your code.
http://omz-software.com/pythonista/docs/ios/ui.html#about-actions-and-delegates
-
@ZinoSama, if you want to do a lot of little animations, you could take a look at scripter (blows dust off the link). With it, you can have several simultaneous and long-running animations without having to worry about the UI thread.
An example of a button click handler running a counter to 100:
@script def start(sender): label = sender.superview["label1"] set_value(label, "text", range(1, 101), lambda count: f"Count: {count}")