【问题标题】:refreshing data inside tkinter loop在 tkinter 循环内刷新数据
【发布时间】:2021-05-27 05:21:30
【问题描述】:

情况:我有一个 tkinter GUI,可以显示从 API 收集的天气数据。我有一个从 API 请求数据的“get_weather”函数。响应通过管道传输到“格式化”函数,然后返回到“get_weather”函数。然后将格式化的字符串显示为 tkinter 标签的文本。该程序旨在在启动时运行(cronjob)并保持连续运行。一切都很好,除了...

问题:我无法让“get_weather”功能自动刷新。我希望“get_weather”函数每 30 分钟运行一次,以将数据从 API 更新到 GUI。

我试过了:一个无限的While循环;这会阻止 Tk 循环启动。在代码中加入 time.sleep(60);停止 GUI 启动一分钟。和 after 方法(请参阅下面的用法)。除非我将时间参数设为一个巨大的数字,否则它似乎没有做任何事情。然后它延迟了 GUI 的启动。

附带说明:我没有自己上课。这是下一次迭代的计划。我只是没有信心上课。在我这样做之前,我想解决其他问题。此外,我在 Tk 循环开始时定义了所有函数。它们在循环中被调用。这对我来说很有意义,但如果有人有理由让他们参与进来,我想听听。我已经学会了线程,但我认为这不是解决方案。

代码如下:(程序300行,还有其他功能,我只是把问题代码总结一下)

from Tkinter import Tk*
import [a few other modules]

def change_location(city):
    # passes a 'city' value from an Entry widget
    # sends request to a geo location api for gps coordinates.
    # saves location coordinates to a local config file.
    getweather()

def formatting(json):
    # takes json from api and formats it to a string
    return string

def get_weather():
    # opens a local config file with gps coordinates.
    # Note: the weather api I'm using requires gps coordinates
    # uses gps coordinates in weather api request
    weather['text'] = formatting(response.json())

# start of tkinter loop
root = Tk()
weather = Label(root)
# manual refresh button that works
refresh = Button(root, text="Refresh", command=get_weather)
new_city = Entry(root)

weather.grid(row=0, column=0)
refresh.grid(row=0, column=1)
new_city.grid(row2, column=1)

# after method like his only seems to delay GUI launch only calls 'get_weather' once. 
# I also tried weather.after(10000, get_weather())
root.after(10000, get_weather)
root.mainloop()

我可以发布完整的代码,但我认为没有人愿意通读 300 行代码来寻找一个简单的解决方案。

编辑:更正按钮命名错误 + 添加 'change_location' 功能到summery

【问题讨论】:

    标签: python loops tkinter nested-loops


    【解决方案1】:

    root.after(1800000, get_weather)也放在get_weather()里面,所以:

    def get_weather():
        root.after(1800000, get_weather) # 30 mins is 1800000 ms
    

    所以现在一旦开始调用该函数,它将每 30 分钟调用一次。

    尽管注意,button 可能打错了,但你忘了把它放在Button() 中。无论如何,如果你按下button,那么这个after() 将被调用两次,从而加快进程。所以建议使用标志来确保按钮只被按下一次,然后禁用按钮。或者寻找另一种选择。我建议不要使用任何按钮。

    【讨论】:

    • 感谢@Cool Cloud。那成功了。是的,我输入按钮错误只是一个错字。我可以取出刷新按钮。它更多地是为了测试而不是为了用户。但我确实有一个面向用户的“change_location”函数,可以更改 get_weather api 请求的参数。它在更新位置值后调用 get_weather 函数。这将遇到同样的复合问题。我确实从 api 中抽出时间。所以我可以用 time 和 after 方法做一个 if 语句来阻止它在 30 分钟过去之前运行。使用标志会更好吗?如何使用标志?
    • @nimic 好吧,你可以使用标志,如何使用标志很长,也超出了这个问题的范围。最好问一个新问题。
    【解决方案2】:

    我找到了解决办法。它不是防故障解决方案,但效果很好。我将 after 方法抽象为另一个函数“刷新器”。 'refresher' 调用 'get_weather' 但 after 方法循环 'refresher' 而不是 'get_weather'。 'refresher' 在 Tk 循环中被调用。

    使用“change_location”函数仍会复合计时器(通过调用“get_weather”)。因为 after 方法附加到不同的函数,所以它只会将计时器复合一个周期。无论哪种方式,计时器都不太可能复杂到足以减慢程序并在下一个周期中更正。

    def refresher():
        get_weather()
        root.after(1800000, refresher)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 2012-12-30
      • 2021-03-01
      • 1970-01-01
      • 2020-04-08
      • 2018-08-04
      相关资源
      最近更新 更多