You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter天气应用返回主界面后,明日预报仍显示旧数据问题

问题分析与解决方案

问题根源

  1. 全局变量引用失效:tomorrow()函数始终引用程序启动时第一次调用opening()返回的city_entry,点击"Go back"后opening()重新创建的新输入框没有更新全局变量,导致再次点击明日预报时仍读取旧输入框内容。
  2. 界面重复创建:goback()里调用opening()会重复生成顶部输入框、框架等元素,旧元素未被销毁导致界面层级混乱,新输入框也无法被tomorrow()识别。
  3. 局部变量覆盖全局:tomorrow()内重新定义的second_frame局部变量覆盖了全局变量,导致后续操作无法正确关联主界面框架。

修复步骤

  • 移除重复调用的opening(),仅在程序启动时初始化一次界面。
  • 让tomorrow()直接读取当前活跃的city_entry内容,避免依赖全局变量的陈旧引用。
  • 修改goback()逻辑,不再重建整个界面,而是清空second_frame并恢复主界面的天气显示区域和明日预报按钮。
  • 统一天气API调用逻辑,消除重复代码。

修复后的完整代码

import tkinter as tk
import requests
from PIL import ImageTk, Image 

window = tk.Tk()
window.geometry('750x500')

# 全局存储当前天气数据,避免重复请求API
current_weather_data = None

def format_response(weather, is_tomorrow=False):
    try:
        name = weather['city']['name']
        # 当日取第0条数据,明日取第1条
        data_index = 1 if is_tomorrow else 0
        temperature = weather['list'][data_index]['main']['temp']
        desc = weather['list'][data_index]['weather'][0]['description']
        temp_feels = weather['list'][data_index]['main']['feels_like']
        humidity = weather['list'][data_index]['main']['humidity']
        wind_speed = weather['list'][data_index]['wind']['speed']

        if is_tomorrow:
            final_str = f'City: {name} \nTemperature tomorrow: {temperature}°C --- will feel like: {temp_feels}°C \nConditions: {desc} \nHumidity: {humidity}% \nWind Speed: {wind_speed}m/s'
        else:
            final_str = f'City: {name} \nTemperature now: {temperature}°C --- feels like: {temp_feels}°C \nConditions: {desc} \nHumidity: {humidity}% \nWind Speed: {wind_speed}m/s'
    except:
        final_str = 'There was a problem retrieving that information'
    return final_str

def get_weather(city):
    global current_weather_data
    weather_key = 'a9f553857df50650433c1577e3be6538'
    url = 'http://api.openweathermap.org/data/2.5/forecast'
    params = {'q': city, 'appid': weather_key, 'units': 'metric'}
    response = requests.get(url, params=params)
    current_weather_data = response.json()
    
    # 清空框架内容并显示当日天气
    clear_second_frame()
    label_below['text'] = format_response(current_weather_data)
    
    # 添加明日预报按钮
    temp_tmr = tk.Button(second_frame, font=('Bookman Old Style', 10), text="Tomorrow's Forecast", command=show_tomorrow_forecast)
    temp_tmr.place(relx=0.74, rely=0.88, relwidth=0.25, relheight=0.1)

def clear_second_frame():
    # 彻底销毁框架内所有控件,避免元素堆积
    for widget in second_frame.winfo_children():
        widget.destroy()

def show_tomorrow_forecast():
    if not current_weather_data:
        return
    clear_second_frame()
    
    # 显示明日天气信息
    label_below2 = tk.Label(second_frame, font=('Bookman Old Style', 15), anchor="nw", justify="left", bd=4)
    label_below2.place(relwidth=1, relheight=1)
    label_below2['text'] = format_response(current_weather_data, is_tomorrow=True)
    
    # 添加返回主界面按钮
    back_btn = tk.Button(second_frame, font=('Bookman Old Style', 10), text="Go back", command=go_back_to_main)
    back_btn.place(relx=0.01, rely=0.88, relwidth=0.12, relheight=0.1)

def go_back_to_main():
    # 返回主界面,恢复当日天气显示和明日预报按钮
    if current_weather_data:
        clear_second_frame()
        label_below['text'] = format_response(current_weather_data)
        temp_tmr = tk.Button(second_frame, font=('Bookman Old Style', 10), text="Tomorrow's Forecast", command=show_tomorrow_forecast)
        temp_tmr.place(relx=0.74, rely=0.88, relwidth=0.25, relheight=0.1)

def resize_image(event):
    new_width = event.width
    new_height = event.height
    image = copy_of_image.resize((new_width, new_height))
    photo = ImageTk.PhotoImage(image)
    label.config(image=photo)
    label.image = photo

# 初始化主界面
image = Image.open('img\\clouds.jpg')
copy_of_image = image.copy()
photo = ImageTk.PhotoImage(image)
label = tk.Label(window, image=photo)
label.bind('<Configure>', resize_image)
label.pack(fill=tk.BOTH, expand=True)

top_frame = tk.Frame(window, bg="#0cc961", bd=5)
top_frame.place(relx=0.1, rely=0.05, relwidth=0.8, relheight=0.15)

city_entry = tk.Entry(top_frame, font=('Bookman Old Style', 22))
city_entry.place(relwidth=0.65, relheight=1)
# 绑定回车键触发查询,提升操作便捷性
city_entry.bind('<Return>', lambda e: get_weather(city_entry.get()))

enter_button = tk.Button(top_frame, font=('Bookman Old Style', 18), text="Enter", command=lambda: get_weather(city_entry.get()))
enter_button.place(relx=0.68, relwidth=0.31, relheight=1)

second_frame = tk.Frame(window, bg="#0cc961", bd=5)
second_frame.place(relx=0.1, rely=0.25, relwidth=0.8, relheight=0.7)

label_below = tk.Label(second_frame, font=('Bookman Old Style', 15), anchor="nw", justify="left", bd=4)
label_below.place(relwidth=1, relheight=1)

window.mainloop()

关键改进点

  • 用current_weather_data全局变量存储天气数据,避免重复调用API。
  • 统一format_response函数,通过参数区分当日/明日数据,减少代码冗余。
  • 改用destroy()彻底销毁控件,避免界面元素堆积。
  • go_back_to_main()直接恢复主界面内容,确保city_entry始终是当前活跃的输入框。
  • 为输入框绑定回车键,符合用户操作习惯。

内容的提问来源于stack exchange,提问作者Josborne

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 00:06:17