0

As title mentions, I'm trying to update the values in my labels in a tkinter gui. The values are taken from OpenWeatherMap API using pyown and at my subscription level, I can only make 60 calls/minute. Since I plan to make many calls, I would like to have my gui update every minute or 5-minutes. I've spent the last few days reading the similar questions and I have figured out that I need the sleep function to delay the update. Some have suggested that I put what I want to repeat in a while True infinite loop, but wheN I tried that, the gui only updated when I closed out the window, and I was unable to control the time in between updates. Others have suggested that I use the .after function, but when I do this, my program compiles but the gui never pops up. I'm looking for someone to show me how either of these solutions work in my code specifically, or if there is a third solution that lends itself better to my code that would be better, please let me see how it would look, because I am stumped.

import tkinter as tk
import pyowm
from datetime import datetime, timedelta

class WeatherInfo(tk.Tk):

    def __init__(self):

        tk.Tk.__init__(self)
        self.wm_title('Forecast')
        self.currentTime = tk.StringVar(self, value='')
        self.d2temp_7 = tk.StringVar(self,value='')
        
        self.owm = pyowm.OWM('*INSERT YOUR OWM KEY HERE*')

        self.headLabel = tk.Label(self, text='5-Day Forecast of Cayce, US.')
        self.headLabel.pack()
        self.footLabel = tk.Label(self, textvariable=self.currentTime)
        self.footLabel.pack(side=tk.BOTTOM)
        
        self.day2Frame = tk.LabelFrame(self, text='D2')
        self.day2Frame.pack(fill='both', expand='yes', side=tk.LEFT)
        tk.Label(self.day2Frame, text="Temperature:").pack()
        tk.Label(self.day2Frame, textvariable=self.d2temp_7).pack()

        self.search()

    def search(self):
        fc = self.owm.three_hours_forecast_at_id(4573888)
        try:
            self.currentTime.set(datetime.today())
            self.d2temp_7.set("7am: " + str(fc.get_weather_at((datetime.today().replace(hour=13, minute=00) + timedelta(days=1))
                                 .strftime ('%Y-%m-%d %H:%M:%S+00')).get_temperature('fahrenheit')['temp']))
        except:
            self.temp.set('Pick a city to display weather.')

    def _quit(self):
        self.quit()
        self.destroy()

if __name__== "__main__":
    app = WeatherInfo()
    app.mainloop()

More on what I have tried:

while True:
    def __init__
    def search

But as this answer points out, other answer , I won't see any changes I make in my while True preceding the root.mainloop()

This question came close to my answer using root.after(milliseconds,results), but when I implimented this answer my gui never showed. infinitely update

Thank you to anyone who tries to answer this.

Edit: I have made my code shorter as per recommendation.

Community
  • 1
  • 1
Purin
  • 56
  • 9
  • This is way too much code. Please condense it down to a [mcve] – Bryan Oakley Nov 11 '17 at 20:06
  • Thank you Bryan for the recommendation. I have made my code example considerably shorter. Good how-to link. – Purin Nov 12 '17 at 01:09
  • How exactly does your `.after` implementation not work? Also check [this](https://stackoverflow.com/a/11505034/7032856) further on that. – Nae Nov 12 '17 at 05:23

1 Answers1

1

Based on this you can have a function,forecast_update, like the following:

import tkinter as tk

#these two needed only for API update simulation
import random
import string

root = tk.Tk()

forecast = tk.Label(text="Forecast will be updated in 60 seconds...")
forecast.pack()

# returns a string with 7 random characters, each time it is called, in order to simulate API
def update_request_from_api():
    return ''.join(random.choice(string.ascii_lowercase) for x in range(7))


# Your function to update the label
def forecast_update():
    forecast.configure(text=update_request_from_api())
    forecast.after(60000, forecast_update) # 60000 ms = 1 minute


# calling the update function once
forecast_update()
root.mainloop()
Nae
  • 14,209
  • 7
  • 52
  • 79
  • The Return function only returns one thing right? As i mentioned in my question, i will be making lots of calls at once (around ~40). Does this mean I need to make a new def for each one? surely there is a better way... – Purin Nov 12 '17 at 21:36
  • 1
    You can return multiple values from a function. Check [this](https://stackoverflow.com/questions/354883/how-do-you-return-multiple-values-in-python) out. – Nae Nov 12 '17 at 21:47