I need to download some files weekly at a time and day specified by the user as shown in the screenshot.
I am struggling with integrating an inner loop with respect to root.mainloop()
.
So far I have tried with .after
and with a while structured like this:
def scaricaAuto(myDay, myHour, myMinute):
while True:
day = datetime.datetime.now().strftime("%A")
hour = datetime.datetime.now().strftime("%H")
minute = datetime.datetime.now().strftime("%M")
if day == myDay and str(int(hour)) == myHour and str(int(minute)) == myMinute:
DownloadButton.invoke()
break
root.after(60000, scaricaAuto(clickedDays.get(), HourSpin.get(), MinSpin.get()))
Using only .after
leads to Python: maximum recursion depth exceeded while calling a Python object
and the while loop doesn't behave properly, when the if is true it gets stucked there and keeps invoking DownloadButton.
Also OS X shows my script to be "not responding" when a button function last longer than a few seconds, is there a solution for this to?
Thanks in advance to those that took the time to read my question and might be able to help me!
CodePudding user response:
There are a couple of problems in your code. First, you need to remove while True
. That serves no purpose. Tkinter is already running an infinite loop by way of mainloop
.
Second, after
requires a function. You're calling a function and passing the result to after
.
In other words, this:
root.after(60000, scaricaAuto(clickedDays.get(), HourSpin.get(), MinSpin.get()))
... is functionally identical to this:
result = scaricaAuto(clicedDays.get(), HourSpin.get(), MinSpin.get())
root.after(60000, result)
Instead, you either need to pass scaricaAuto
as an argument, or you need to create a new function that calls your function. In the case of the former, you can pass arguments to the function by passing those arguments to after
.
For example,
root.after(60000, scaricaAuto, clickedDays.get(), HourSpin.get(), MinSpin.get())
Note that this calls the .get()
functions immediately rather than waiting the full 60 seconds.
A better solution is to not pass any arguments to scaricaAuto
and instead have it call the .get()
methods right when it needs the values:
def scaricaAuto():
myDay = clickedDays.get()
myHour = HourSpin.get()
myMinute = MinSpin.get()
now = datetime.datetime.now()
day = now.strftime("%A")
hour = now.strftime("%H")
minute = now.strftime("%M")
if day == myDay and str(int(hour)) == myHour and str(int(minute)) == myMinute:
DownloadButton.invoke()
root.after(60000, scaricaAuto)
The above code will run for as long as the GUI itself is running, assuming you've called mainloop
at some point.