import tkinter as tk
import random
import math
from datetime import datetime, timedelta
class WeatherSimulator:
def __init__(self, root):
self.root = root
self.root.title("天气预报模拟器")
self.root.geometry("900x600")
# 模拟参数
self.current_time = datetime.now().replace(hour=0, minute=0, second=0)
self.time_scale = 10 # 时间缩放因子(1秒模拟多少分钟)
self.is_running = False
# 创建温度数据
self.temperatures = self.generate_realistic_temperatures()
# 创建界面
self.create_widgets()
# 启动模拟
self.update()
def generate_realistic_temperatures(self):
"""生成符合真实天气变化规律的24小时温度数据"""
temperatures = []
base_temp = random.uniform(15, 25) # 随机基础温度
# 使用正弦函数模拟温度变化
for hour in range(24):
# 凌晨温度最低,下午温度最高
temp = base_temp + 8 * math.sin((hour - 6) * math.pi / 12)
# 添加随机波动
if hour < 6: # 凌晨
temp += random.uniform(-1, 0.5)
elif hour < 12: # 上午
temp += random.uniform(-0.5, 1)
elif hour < 18: # 下午
temp += random.uniform(0, 1.5)
else: # 晚上
temp += random.uniform(-0.5, 1)
temperatures.append(round(temp, 1))
return temperatures
def create_widgets(self):
"""创建界面组件"""
# 控制面板
control_frame = tk.Frame(self.root, bg="#f0f0f0", padx=10, pady=10)
control_frame.pack(fill=tk.X)
self.time_label = tk.Label(control_frame, text="时间: 00:00", font=("Arial", 12))
self.time_label.pack(side=tk.LEFT, padx=10)
self.temp_label = tk.Label(control_frame, text="当前温度: --°C", font=("Arial", 12))
self.temp_label.pack(side=tk.LEFT, padx=10)
self.play_btn = tk.Button(control_frame, text="开始", command=self.toggle_simulation)
self.play_btn.pack(side=tk.RIGHT, padx=5)
speed_frame = tk.Frame(control_frame)
speed_frame.pack(side=tk.RIGHT, padx=10)
tk.Label(speed_frame, text="速度:").pack(side=tk.LEFT)
self.speed_var = tk.IntVar(value=self.time_scale)
speed_scale = tk.Scale(speed_frame, from_=1, to=60, orient=tk.HORIZONTAL,
variable=self.speed_var, showvalue=False, length=100)
speed_scale.pack(side=tk.LEFT)
self.speed_label = tk.Label(speed_frame, text=f"{self.time_scale}x")
self.speed_label.pack(side=tk.LEFT)
# 图表区域
chart_frame = tk.Frame(self.root)
chart_frame.pack(fill=tk.BOTH, expand=True, padx=20, pady=10)
self.canvas = tk.Canvas(chart_frame, bg="white", bd=2, relief=tk.GROOVE)
self.canvas.pack(fill=tk.BOTH, expand=True)
# 状态栏
self.status_bar = tk.Label(self.root, text="就绪", bd=1, relief=tk.SUNKEN, anchor=tk.W)
self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)
def toggle_simulation(self):
"""开始/暂停模拟"""
self.is_running = not self.is_running
self.play_btn.config(text="暂停" if self.is_running else "开始")
self.status_bar.config(text="模拟运行中..." if self.is_running else "模拟已暂停")
def update(self):
"""更新模拟状态"""
if self.is_running:
# 更新时间
self.time_scale = self.speed_var.get()
self.speed_label.config(text=f"{self.time_scale}x")
minutes_to_add = self.time_scale
self.current_time += timedelta(minutes=minutes_to_add)
# 如果超过24小时,重置时间并生成新温度数据
if self.current_time.hour == 0 and self.current_time.minute < minutes_to_add:
self.temperatures = self.generate_realistic_temperatures()
self.status_bar.config(text="新的一天开始,生成新的温度数据")
# 更新UI
self.update_time_label()
self.draw_chart()
# 每100毫秒更新一次
self.root.after(100, self.update)
def update_time_label(self):
"""更新时间标签"""
time_str = self.current_time.strftime("%H:%M")
self.time_label.config(text=f"时间: {time_str}")
# 获取当前温度
hour = self.current_time.hour
minute = self.current_time.minute
minute_fraction = minute / 60.0
# 线性插值计算当前分钟的温度
if hour < 23:
current_temp = self.temperatures[hour] + (self.temperatures[hour+1] - self.temperatures[hour]) * minute_fraction
else:
current_temp = self.temperatures[23] # 使用最后一个小时的温度
self.temp_label.config(text=f"当前温度: {current_temp:.1f}°C")
def draw_chart(self):
"""绘制温度折线图"""
self.canvas.delete("all")
width = self.canvas.winfo_width()
height = self.canvas.winfo_height()
if width <= 10 or height <= 10:
return
# 设置图表边距
margin = 50
chart_width = width - 2 * margin
chart_height = height - 2 * margin
# 绘制坐标轴
self.canvas.create_line(margin, margin, margin, height - margin, width=2) # Y轴
self.canvas.create_line(margin, height - margin, width - margin, height - margin, width=2) # X轴
# 绘制刻度和标签
min_temp = min(self.temperatures) - 2
max_temp = max(self.temperatures) + 2
# Y轴刻度和标签
for i in range(0, 11):
y = height - margin - i * (chart_height / 10)
temp_val = min_temp + i * (max_temp - min_temp) / 10
self.canvas.create_line(margin - 5, y, margin, y, width=1)
self.canvas.create_text(margin - 10, y, text=f"{temp_val:.1f}°", anchor=tk.E)
# X轴刻度和标签(小时)
for hour in range(0, 24, 3):
x = margin + hour * (chart_width / 24)
self.canvas.create_line(x, height - margin, x, height - margin + 5, width=1)
self.canvas.create_text(x, height - margin + 20, text=f"{hour:02d}:00")
# 绘制温度曲线
points = []
for hour, temp in enumerate(self.temperatures):
x = margin + hour * (chart_width / 24)
y = height - margin - ((temp - min_temp) / (max_temp - min_temp)) * chart_height
points.append((x, y))
# 绘制温度点
self.canvas.create_oval(x-3, y-3, x+3, y+3, fill="blue")
# 绘制折线
if len(points) > 1:
self.canvas.create_line(points, fill="blue", width=2, smooth=True)
# 绘制当前时间线
current_hour = self.current_time.hour + self.current_time.minute / 60.0
current_x = margin + current_hour * (chart_width / 24)
self.canvas.create_line(current_x, margin, current_x, height - margin,
fill="red", dash=(4, 2), width=1)
# 绘制标题
self.canvas.create_text(width/2, 20, text="24小时温度变化趋势",
font=("Arial", 14, "bold"))
# 绘制图例
self.canvas.create_rectangle(width - 120, 30, width - 20, 80, fill="#f0f0f0", outline="gray")
self.canvas.create_text(width - 70, 40, text="图例", font=("Arial", 10, "bold"))
self.canvas.create_line(width - 110, 60, width - 80, 60, fill="blue", width=2)
self.canvas.create_text(width - 65, 60, text="温度", anchor=tk.W)
self.canvas.create_line(width - 110, 75, width - 80, 75, fill="red", dash=(4, 2), width=1)
self.canvas.create_text(width - 65, 75, text="当前时间", anchor=tk.W)
# 创建主窗口并启动应用
if __name__ == "__main__":
root = tk.Tk()
app = WeatherSimulator(root)
root.mainloop()
把他改为折线图,48小时温度
最新发布