如何在Tkinter Label中完整显示OpenWeatherMap多日天气预报?
解决Tkinter Label无法显示多日天气预报的问题
我一眼就看出问题出在你的format_response函数里——你每次循环都直接把新的天气数据覆盖到final_str上,而不是把内容累加起来!
问题根源
在你的原代码中:
def format_response(weather): for i in range(10): # ... 生成当天天气的代码 ... final_str = 'Date: %s ...' %(...) # 每次循环都覆盖final_str return(final_str)
循环执行10次,但每次都会把final_str重置为当天的天气内容,最后返回的只是第10次循环的结果,所以Label只能显示单日预报。而用print的话,每次循环都会打印一次,所以Python Shell能看到所有内容,但return只能返回最后一次的值。
修复方案
我们需要初始化一个空字符串,然后在每次循环中把当天的天气信息追加进去,这样最后返回的就是所有天数的完整内容:
def format_response(weather): final_str = "" # 初始化空字符串 for i in range(10): dt_txt = weather['list'][i]['dt'] date = (datetime.fromtimestamp(dt_txt)).strftime('%d-%b-%Y %H:%M:%S') desc = weather['list'][i]['weather'][0]['description'] temp_min = weather['list'][i]['main']['temp_min'] temp_max = weather['list'][i]['main']['temp_max'] # 生成当天的天气字符串,加上换行和分隔空行提升可读性 day_weather = 'Date: %s \nConditions: %s \nMin.Temperature(Celsius): %s\nMax.Temperature(Celsius): %s\n\n' %(date, desc, temp_min, temp_max) final_str += day_weather # 追加到总字符串里 return final_str
完整修改后的代码
import tkinter as tk from tkinter import font from PIL import ImageTk, Image import requests from datetime import datetime HEIGHT = 700 WIDTH = 700 def format_response(weather): final_str = "" for i in range(10): dt_txt = weather['list'][i]['dt'] date = (datetime.fromtimestamp(dt_txt)).strftime('%d-%b-%Y %H:%M:%S') desc = weather['list'][i]['weather'][0]['description'] temp_min = weather['list'][i]['main']['temp_min'] temp_max = weather['list'][i]['main']['temp_max'] day_weather = 'Date: %s \nConditions: %s \nMin.Temperature(Celsius): %s\nMax.Temperature(Celsius): %s\n\n' %(date, desc, temp_min, temp_max) final_str += day_weather return final_str def get_weather(city): api_key = 'a4aa5e3d83ffefaba8c00284de6ef7c3' url = 'https://api.openweathermap.org/data/2.5/forecast' params = {'APPID': api_key, 'q': city, 'units': 'metric'} response = requests.get(url, params = params) weather = response.json() label['text'] = format_response(weather) root = tk.Tk() canvas = tk.Canvas(root, height = HEIGHT, width = WIDTH) canvas.pack() background_image = ImageTk.PhotoImage(Image.open("D:/Documents/Python/GUI/Weather App/beach.png")) background_label = tk.Label(root, image = background_image) background_label.place(relwidth = 1, relheight = 1) frame = tk.Frame(root, bg = '#b1cfff', bd = 5) frame.place(relx = 0.5, rely = 0.15, relwidth = 0.80, relheight = 0.05, anchor = 'n') entry = tk.Entry(frame, bg='#fce300', font = 40) entry.place(relx = 0.0, rely = 0, relwidth = 0.75, relheight = 1) button = tk.Button(frame, text = "SEARCH", font = 40, bg = 'black', fg = 'yellow', command = lambda: get_weather(entry.get())) button.place(relx = 0.758, rely = 0, relwidth = 0.24, relheight = 1) lower_frame = tk.Frame(root, bg = '#b1cfff', bd = 5) lower_frame.place(relx = 0.5, rely = 0.25, relwidth = 0.80, relheight = 0.6, anchor = 'n') label = tk.Label(lower_frame, font = ('courier new',10), bg = '#fce300', anchor = 'nw', justify = 'left') label.place(relwidth = 1, relheight = 1) root.mainloop()
额外提示
如果想显示每日汇总(而不是每3小时一次的数据),你可以根据日期分组,只保留每天的第一条记录或计算每日的平均/最高最低温,但这属于额外功能,你可以根据需求调整。
内容的提问来源于stack exchange,提问作者Wazzup83




