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.
Close Timer in ui Custom Class using @ui.in_background
-
I wanted an auto_close function (async) in a custom ui.View class. I wanted to keep it as simple as possible without using date time and keeping the interface responsive . It's not meant to be exact, but close.
date time is used, just to to test the approx accuracy.
Below is a test of what is in my real class. I think the variance could easily be put down to other factors. Just post in case someone has some comments. This is not my forte, but I was happy with my solution. But opened to being to told I lost the plot.import ui import datetime, time class Test (ui.View): def __init__(self, duration = 1.0): self.frame = (0,0,300,300) self.background_color = 'white' btn = ui.Button(title = 'start') btn.width = 100 btn.border_width = .5 # hmmmmmmm, center does not work ( as you would expect it too ) # eg. btn.center = self.center btn.center = (self.center[0], self.center[1] - (44/2)) btn.action = self.auto_close_timer self.add_subview(btn) self.auto_close_duration = float(duration) @ui.in_background def auto_close_timer(self, sender): # try to stay responsive regardless of the time # set. its not meant to be exact, but its very close # for this close enough sender.enabled = False n = self.auto_close_duration st = datetime.datetime.now() while True: n -= self.auto_close_duration / 10. if n < 0.0 : break time.sleep(self.auto_close_duration / 10.) #print datetime.datetime.now() - st self.name = str(datetime.datetime.now() - st) sender.enabled = True if __name__ == '__main__': t = Test(1.5) t.present('sheet')
-
@Phuket2 Why not just use ui.delay rather than a sleep loop? If this is supposed to be an inactivity timer, you could just use ui.cancel_delay whenever activity is detected.
Also, if there is the possibility of any other ui.in_background happening at the same time, you need to use ui.delay or a threading.thread, ( or see my run_async decorator that I have posted before) as no other ui.in_background calls will start until this one has completed.
-
@JonB , I want to cry sometimes. BUT yes, you are 100% correct. Thank you. But that's why I post. It would be horrible to have my code when such an elegant solution is there starring me in the face. But it's my learning curve, I guess.
Maybe that crazy crap I come up with will come in handy one day 😁 -
@JonB , revised version of the test code. is a lot of extra just for testing. But so clean now for the timer part. Also a lot more accurate timings . Thanks again
import ui import datetime, time class Test (ui.View): def __init__(self, duration = 1.0): self.frame = (0,0,300,300) self.background_color = 'white' btn = ui.Button(title = 'start') btn.width = 100 btn.border_width = .5 # hmmmmmmm, center does not work ( as you would expect it too ) # eg. btn.center = self.center btn.center = (self.center[0], self.center[1] - (44/2)) btn.action = self.JonB_way self.fire_obj = btn self.add_subview(btn) self.auto_close_duration = float(duration) self.start = None def JonB_way(self, sender): self.fire_obj.enabled = False self.start = datetime.datetime.now() ui.delay(self.fire_delay, self.auto_close_duration) def fire_delay(self): self.name = str(datetime.datetime.now() - self.start) self.fire_obj.enabled = True