天气组件UI优化

pull/91/head
Maziang 4 months ago
parent 660a12abac
commit 77e613b8d7

@ -464,17 +464,125 @@ class WordRibbon(QFrame):
"""主题切换槽函数"""
self.apply_theme()
def get_weather_emoji(self, weather_desc):
"""根据天气描述返回对应的emoji图标"""
weather_emoji_map = {
'': '🌞',
'多云': '☁️',
'': '☁️',
'小雨': '🌦️',
'中雨': '🌧️',
'大雨': '⛈️',
'暴雨': '⛈️',
'雷阵雨': '⛈️',
'': '❄️',
'小雪': '🌨️',
'中雪': '❄️',
'大雪': '❄️',
'暴雪': '❄️',
'': '🌫️',
'': '🌫️',
'沙尘暴': '🌪️',
'扬沙': '🌪️',
'浮尘': '🌪️',
'台风': '🌀',
'飓风': '🌀',
'龙卷风': '🌪️',
'冰雹': '🧊',
'冻雨': '🌨️',
'雨夹雪': '🌨️',
'sunny': '🌞',
'clear': '🌞',
'cloudy': '☁️',
'overcast': '☁️',
'rain': '🌧️',
'light rain': '🌦️',
'heavy rain': '⛈️',
'thunderstorm': '⛈️',
'snow': '❄️',
'fog': '🌫️',
'haze': '🌫️',
'sandstorm': '🌪️',
'typhoon': '🌀',
'hurricane': '🌀',
'tornado': '🌪️',
'hail': '🧊'
}
# 模糊匹配天气描述
weather_desc_lower = str(weather_desc).lower()
for key, emoji in weather_emoji_map.items():
if key in weather_desc_lower:
return emoji
# 默认返回晴天图标
return '🌞'
def create_weather_group(self):
"""创建天气组件组"""
if self.weather_group is not None:
return self.weather_group
weather_group = self.create_ribbon_group("天气")
weather_group.setFixedWidth(200) # 增加整体宽度
weather_layout = QVBoxLayout()
weather_layout.setSpacing(8) # 增加行间距
# 第一行:天气图标和温度显示(居中对齐)
weather_display_layout = QHBoxLayout()
weather_display_layout.setSpacing(10) # 增加图标和温度间距
# 添加左侧弹性空间,推动内容到中心
weather_display_layout.addStretch()
# 天气图标标签 - 优化垂直居中对齐
self.weather_icon_label = QLabel("🌞")
self.weather_icon_label.setAlignment(Qt.AlignCenter) # 使用Qt对齐方式
self.weather_icon_label.setStyleSheet("""
QLabel {
font-size: 32px;
padding: 0px;
margin: 0px;
border: none;
background: transparent;
}
""")
self.weather_icon_label.setFixedSize(40, 40) # 增大图标尺寸
# 温度标签 - 优化垂直居中对齐
self.weather_temp_label = QLabel("--°C")
self.weather_temp_label.setAlignment(Qt.AlignVCenter | Qt.AlignLeft) # 使用Qt对齐方式
self.weather_temp_label.setStyleSheet("""
QLabel {
font-size: 16px;
font-weight: bold;
color: #333333;
padding: 0px;
margin: 0px;
border: none;
background: transparent;
min-height: 30px; /* 确保最小高度 */
}
""")
self.weather_temp_label.setFixedSize(70, 30) # 增加温度标签宽度
weather_display_layout.addWidget(self.weather_icon_label)
weather_display_layout.addWidget(self.weather_temp_label)
# 添加右侧弹性空间,确保内容居中
weather_display_layout.addStretch()
# 第二行:城市选择和刷新按钮(居中对齐)
control_layout = QHBoxLayout()
control_layout.setSpacing(8) # 增加控件间距
# 添加左侧弹性空间,推动内容到中心
control_layout.addStretch()
# 城市选择 - 添加所有省会城市
self.city_combo = QComboBox()
self.city_combo.setFixedWidth(120) # 增加宽度以显示完整城市名
self.city_combo.setFixedWidth(120) # 增加城市选择框宽度
self.city_combo.setStyleSheet("QComboBox { font-size: 12px; padding: 3px; }") # 增大字体和间距
self.city_combo.addItems([
'自动定位',
'北京', '上海', '广州', '深圳', '杭州', '南京', '武汉', '成都', '西安', # 一线城市
@ -487,12 +595,20 @@ class WordRibbon(QFrame):
self.city_combo.currentTextChanged.connect(self.on_city_changed)
# 刷新按钮
self.refresh_weather_btn = QPushButton("刷新天气")
self.refresh_weather_btn = QPushButton("🔄 刷新")
self.refresh_weather_btn.clicked.connect(self.on_refresh_weather)
self.refresh_weather_btn.setFixedSize(80, 25)
self.refresh_weather_btn.setFixedSize(60, 30) # 增大刷新按钮尺寸
self.refresh_weather_btn.setStyleSheet("QPushButton { font-size: 11px; padding: 5px; }")
self.refresh_weather_btn.setToolTip("刷新天气")
control_layout.addWidget(self.city_combo)
control_layout.addWidget(self.refresh_weather_btn)
# 添加右侧弹性空间,确保内容居中
control_layout.addStretch()
weather_layout.addWidget(self.city_combo)
weather_layout.addWidget(self.refresh_weather_btn)
weather_layout.addLayout(weather_display_layout)
weather_layout.addLayout(control_layout)
weather_group.setLayout(weather_layout)
self.weather_group = weather_group
@ -1016,14 +1132,17 @@ class WeatherAPI:
# 使用免费的天气API
url = f"http://t.weather.sojson.com/api/weather/city/{city_id}"
print(f"获取当前天气: {url}")
response = requests.get(url, timeout=10)
response = requests.get(url, timeout=5) # 减少超时时间
response.raise_for_status()
data = response.json()
print(f"当前天气响应: {data}")
if data['status'] == 200:
city_info = data['cityInfo']
current_data = data['data']
if data.get('status') == 200:
city_info = data.get('cityInfo', {})
current_data = data.get('data', {})
if not current_data:
print("天气数据为空")
return None
# 获取生活提示信息
life_tips = []
@ -1047,20 +1166,35 @@ class WeatherAPI:
while len(life_tips) < 3 and default_tips:
life_tips.append(default_tips.pop(0))
# 安全获取天气数据
wendu = current_data.get('wendu', 'N/A')
shidu = current_data.get('shidu', 'N/A')
first_forecast = forecast[0] if forecast else {}
weather_info = {
'temp': current_data['wendu'],
'feels_like': current_data['wendu'], # 没有体感温度,用实际温度代替
'weather': current_data['forecast'][0]['type'],
'humidity': current_data['shidu'].replace('%', ''),
'wind_dir': current_data['forecast'][0]['fx'],
'temp': wendu,
'feels_like': wendu, # 没有体感温度,用实际温度代替
'weather': first_forecast.get('type', ''), # 默认晴天
'humidity': shidu.replace('%', '') if shidu != 'N/A' else '50',
'wind_dir': first_forecast.get('fx', '无风'),
'wind_scale': '1', # 没有风力等级,用默认值
'vis': current_data['forecast'][0]['high'], # 用最高温作为可见度
'vis': first_forecast.get('high', '高温 15℃'), # 用最高温作为可见度
'pressure': '1013', # 没有气压,用默认值
'life_tips': life_tips # 添加生活提示信息
}
print(f"解析后的天气信息: {weather_info}")
return weather_info
print(f"获取天气失败,状态码: {data.get('status')}")
else:
print(f"获取天气失败,状态码: {data.get('status')}")
return None
except requests.exceptions.Timeout:
print("获取天气超时")
return None
except requests.exceptions.RequestException as e:
print(f"网络请求失败: {e}")
return None
except json.JSONDecodeError as e:
print(f"JSON解析失败: {e}")
return None
except Exception as e:
print(f"获取当前天气失败: {e}")

@ -1295,6 +1295,12 @@ class WordStyleMainWindow(QMainWindow):
"""更新天气显示"""
if 'error' in weather_data:
self.status_bar.showMessage(f"天气数据获取失败: {weather_data['error']}", 3000)
# 更新工具栏天气显示为错误状态
if hasattr(self, 'ribbon'):
if hasattr(self.ribbon, 'weather_icon_label'):
self.ribbon.weather_icon_label.setText("")
if hasattr(self.ribbon, 'weather_temp_label'):
self.ribbon.weather_temp_label.setText("--°C")
else:
# 处理嵌套的天气数据结构
city = weather_data.get('city', '未知城市')
@ -1318,6 +1324,32 @@ class WordStyleMainWindow(QMainWindow):
weather_message = f"{city}: {desc}, {temp}°C{temp_range}"
self.status_bar.showMessage(weather_message, 5000)
# 更新工具栏天气图标和温度显示
if hasattr(self, 'ribbon'):
# 更新天气图标
if hasattr(self.ribbon, 'weather_icon_label') and desc != 'N/A':
emoji = self.ribbon.get_weather_emoji(desc)
self.ribbon.weather_icon_label.setText(emoji)
# 更新温度显示
if hasattr(self.ribbon, 'weather_temp_label') and temp != 'N/A':
# 计算平均温度(使用最高温和最低温的平均值)
avg_temp = temp
if 'forecast' in weather_data and weather_data['forecast']:
forecast_data = weather_data['forecast'][0]
if isinstance(forecast_data, dict):
temp_max = forecast_data.get('temp_max', 'N/A')
temp_min = forecast_data.get('temp_min', 'N/A')
if temp_max != 'N/A' and temp_min != 'N/A':
try:
avg_temp = (float(temp_max) + float(temp_min)) / 2
avg_temp = round(avg_temp, 1)
except (ValueError, TypeError):
avg_temp = temp
temp_str = f"{avg_temp}°C" if isinstance(avg_temp, (int, float)) else f"{temp}°C"
self.ribbon.weather_temp_label.setText(temp_str)
# 存储天气数据供其他功能使用(确保包含生活提示)
self.current_weather_data = weather_data
print(f"update_weather_display - 存储的current_weather_data包含life_tips: {self.current_weather_data.get('life_tips', [])}")

Loading…
Cancel
Save