首页 > 解决方案 > 如何从用户使用 tkinter 决定的日期开始每周安排一次任务?

问题描述

我需要每周在用户指定的时间和日期下载一些文件,如屏幕截图所示。我正在努力整合一个关于root.mainloop(). 到目前为止,我已经尝试过.after一段时间的结构如下:

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()))

仅使用.after会导致Python: maximum recursion depth exceeded while calling a Python objectwhile 循环无法正常运行,当 if 为真时,它会卡在那里并继续调用 DownloadButton。

当按钮功能持续超过几秒钟时,OS X 还显示我的脚本“没有响应”,有解决方案吗?

提前感谢那些花时间阅读我的问题并可能能够帮助我的人!

标签: pythonpython-3.xtkinterscheduled-tasks

解决方案


您的代码中有几个问题。首先,您需要删除while True. 那没有任何意义。Tkinter 已经通过mainloop.

第二,after需要一个函数。您正在调用一个函数并将结果传递给after.

换句话说,这:

root.after(60000, scaricaAuto(clickedDays.get(), HourSpin.get(), MinSpin.get()))

...在功能上与此相同:

result = scaricaAuto(clicedDays.get(), HourSpin.get(), MinSpin.get())
root.after(60000, result)

相反,您需要scaricaAuto作为参数传递,或者您需要创建一个调用您的函数的新函数。在前者的情况下,您可以通过将这些参数传递给函数来将参数传递给after.

例如,

root.after(60000, scaricaAuto, clickedDays.get(), HourSpin.get(), MinSpin.get())

请注意,这会.get()立即调用函数,而不是等待整整 60 秒。

更好的解决方案是不传递任何参数scaricaAuto,而是让它.get()在需要值时正确调用方法:

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)

只要 GUI 本身正在运行,上面的代码就会一直运行,假设您mainloop在某个时候调用过。


推荐阅读