|
|
|
|
@ -39,7 +39,7 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
"""设置UI界面"""
|
|
|
|
|
# 设置窗口属性
|
|
|
|
|
self.setWindowTitle("天气")
|
|
|
|
|
self.setFixedSize(360, 280) # 调整窗口尺寸使其更紧凑
|
|
|
|
|
self.setFixedSize(320, 240) # 调整窗口尺寸使其更紧凑
|
|
|
|
|
|
|
|
|
|
# 创建主框架,用于实现圆角和阴影效果
|
|
|
|
|
self.main_frame = QFrame()
|
|
|
|
|
@ -52,25 +52,22 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
|
|
|
|
|
# 内容布局
|
|
|
|
|
content_layout = QVBoxLayout(self.main_frame)
|
|
|
|
|
content_layout.setContentsMargins(10, 10, 10, 10) # 减小内边距使布局更紧凑
|
|
|
|
|
content_layout.setSpacing(6) # 减小间距使布局更紧凑
|
|
|
|
|
|
|
|
|
|
# 设置最小尺寸策略
|
|
|
|
|
self.main_frame.setMinimumSize(380, 300)
|
|
|
|
|
content_layout.setContentsMargins(12, 12, 12, 12) # 优化内边距
|
|
|
|
|
content_layout.setSpacing(8) # 优化间距
|
|
|
|
|
|
|
|
|
|
# 标题栏
|
|
|
|
|
title_layout = QHBoxLayout()
|
|
|
|
|
title_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
title_layout.setSpacing(0)
|
|
|
|
|
|
|
|
|
|
self.title_label = QLabel("天气信息")
|
|
|
|
|
self.title_label.setFont(QFont("Arial", 12, QFont.Bold))
|
|
|
|
|
title_layout.addWidget(self.title_label)
|
|
|
|
|
title_layout.addStretch()
|
|
|
|
|
# 添加一个小的固定空间,使关闭按钮向左移动
|
|
|
|
|
title_layout.addSpacing(25) # 向左移动25个单位
|
|
|
|
|
|
|
|
|
|
# 关闭按钮
|
|
|
|
|
# 关闭按钮 - 修复被遮挡问题
|
|
|
|
|
self.close_btn = QPushButton("×")
|
|
|
|
|
self.close_btn.setFixedSize(20, 20)
|
|
|
|
|
self.close_btn.setFixedSize(24, 24)
|
|
|
|
|
self.close_btn.setObjectName("closeButton")
|
|
|
|
|
title_layout.addWidget(self.close_btn)
|
|
|
|
|
|
|
|
|
|
@ -80,31 +77,32 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
separator = QFrame()
|
|
|
|
|
separator.setFrameShape(QFrame.HLine)
|
|
|
|
|
separator.setObjectName("separator")
|
|
|
|
|
separator.setFixedHeight(1)
|
|
|
|
|
content_layout.addWidget(separator)
|
|
|
|
|
|
|
|
|
|
# 天气图标和温度显示区域
|
|
|
|
|
weather_display_layout = QHBoxLayout()
|
|
|
|
|
weather_display_layout.setSpacing(5) # 减小间距使布局更紧凑
|
|
|
|
|
weather_display_layout.setContentsMargins(2, 2, 2, 2) # 减小内边距
|
|
|
|
|
weather_display_layout.setSpacing(10)
|
|
|
|
|
weather_display_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
|
|
|
|
|
self.weather_icon_label = QLabel("🌞")
|
|
|
|
|
self.weather_icon_label.setFont(QFont("Arial", 24)) # 稍微减小字体大小
|
|
|
|
|
self.weather_icon_label.setFont(QFont("Arial", 28))
|
|
|
|
|
self.weather_icon_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
self.weather_icon_label.setFixedSize(50, 50) # 减小尺寸
|
|
|
|
|
self.weather_icon_label.setFixedSize(60, 60)
|
|
|
|
|
weather_display_layout.addWidget(self.weather_icon_label)
|
|
|
|
|
|
|
|
|
|
# 温度和城市信息
|
|
|
|
|
temp_city_layout = QVBoxLayout()
|
|
|
|
|
temp_city_layout.setSpacing(4) # 减小间距使布局更紧凑
|
|
|
|
|
temp_city_layout.setSpacing(4)
|
|
|
|
|
temp_city_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
|
|
|
|
|
self.temperature_label = QLabel("25°C")
|
|
|
|
|
self.temperature_label.setFont(QFont("Arial", 18, QFont.Bold)) # 稍微减小字体大小
|
|
|
|
|
self.temperature_label.setFont(QFont("Arial", 20, QFont.Bold))
|
|
|
|
|
self.temperature_label.setObjectName("temperatureLabel")
|
|
|
|
|
temp_city_layout.addWidget(self.temperature_label)
|
|
|
|
|
|
|
|
|
|
self.city_label = QLabel("北京")
|
|
|
|
|
self.city_label.setFont(QFont("Arial", 11)) # 稍微减小字体大小
|
|
|
|
|
self.city_label.setFont(QFont("Arial", 12))
|
|
|
|
|
self.city_label.setObjectName("cityLabel")
|
|
|
|
|
temp_city_layout.addWidget(self.city_label)
|
|
|
|
|
|
|
|
|
|
@ -115,79 +113,88 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
|
|
|
|
|
# 天气描述
|
|
|
|
|
self.weather_desc_label = QLabel("晴天")
|
|
|
|
|
self.weather_desc_label.setFont(QFont("Arial", 11)) # 稍微减小字体大小
|
|
|
|
|
self.weather_desc_label.setFont(QFont("Arial", 12))
|
|
|
|
|
self.weather_desc_label.setObjectName("weatherDescLabel")
|
|
|
|
|
self.weather_desc_label.setAlignment(Qt.AlignCenter)
|
|
|
|
|
content_layout.addWidget(self.weather_desc_label)
|
|
|
|
|
|
|
|
|
|
# 详细信息(湿度、风速)
|
|
|
|
|
details_layout = QHBoxLayout()
|
|
|
|
|
details_layout.setSpacing(6) # 减小间距使布局更紧凑
|
|
|
|
|
details_layout.setContentsMargins(2, 2, 2, 2) # 减小内边距
|
|
|
|
|
details_layout.setSpacing(12)
|
|
|
|
|
details_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
|
|
|
|
|
self.humidity_label = QLabel("湿度: 45%")
|
|
|
|
|
self.humidity_label.setFont(QFont("Arial", 10)) # 稍微减小字体大小
|
|
|
|
|
self.humidity_label.setFont(QFont("Arial", 11))
|
|
|
|
|
self.humidity_label.setObjectName("detailLabel")
|
|
|
|
|
details_layout.addWidget(self.humidity_label)
|
|
|
|
|
|
|
|
|
|
self.wind_label = QLabel("风速: 2级")
|
|
|
|
|
self.wind_label.setFont(QFont("Arial", 10)) # 稍微减小字体大小
|
|
|
|
|
self.wind_label.setFont(QFont("Arial", 11))
|
|
|
|
|
self.wind_label.setObjectName("detailLabel")
|
|
|
|
|
details_layout.addWidget(self.wind_label)
|
|
|
|
|
|
|
|
|
|
details_layout.addStretch()
|
|
|
|
|
content_layout.addLayout(details_layout)
|
|
|
|
|
|
|
|
|
|
# 城市选择区域
|
|
|
|
|
city_layout = QHBoxLayout()
|
|
|
|
|
city_layout.setSpacing(6) # 减小间距使布局更紧凑
|
|
|
|
|
city_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
# 添加弹性空间
|
|
|
|
|
content_layout.addStretch()
|
|
|
|
|
|
|
|
|
|
# 城市选择和按钮区域
|
|
|
|
|
control_layout = QHBoxLayout()
|
|
|
|
|
control_layout.setSpacing(8)
|
|
|
|
|
control_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
|
|
|
|
|
# 城市选择下拉框
|
|
|
|
|
self.city_combo = QComboBox()
|
|
|
|
|
self.city_combo.setObjectName("cityCombo")
|
|
|
|
|
# 添加所有省会城市,与主窗口保持一致
|
|
|
|
|
self.city_combo.addItems([
|
|
|
|
|
'自动定位',
|
|
|
|
|
'北京', '上海', '广州', '深圳', '杭州', '南京', '武汉', '成都', '西安', # 一线城市
|
|
|
|
|
'天津', '重庆', '苏州', '青岛', '大连', '宁波', '厦门', '无锡', '佛山', # 新一线城市
|
|
|
|
|
'石家庄', '太原', '呼和浩特', '沈阳', '长春', '哈尔滨', # 东北华北
|
|
|
|
|
'合肥', '福州', '南昌', '济南', '郑州', '长沙', '南宁', '海口', # 华东华中华南
|
|
|
|
|
'贵阳', '昆明', '拉萨', '兰州', '西宁', '银川', '乌鲁木齐' # 西南西北
|
|
|
|
|
'自动定位',
|
|
|
|
|
# 直辖市
|
|
|
|
|
'北京', '上海', '天津', '重庆',
|
|
|
|
|
# 省会城市
|
|
|
|
|
'石家庄', '太原', '呼和浩特', '沈阳', '长春', '哈尔滨', '南京', '杭州', '合肥', '福州',
|
|
|
|
|
'南昌', '济南', '郑州', '武汉', '长沙', '广州', '南宁', '海口', '成都', '贵阳',
|
|
|
|
|
'昆明', '拉萨', '西安', '兰州', '西宁', '银川', '乌鲁木齐',
|
|
|
|
|
# 特别行政区
|
|
|
|
|
'香港', '澳门',
|
|
|
|
|
# 台湾省主要城市
|
|
|
|
|
'台北', '高雄',
|
|
|
|
|
# 主要地级市和经济中心城市
|
|
|
|
|
'深圳', '青岛', '大连', '宁波', '厦门', '苏州', '无锡', '佛山', '东莞', '中山',
|
|
|
|
|
'泉州', '南通', '常州', '徐州', '温州', '烟台', '威海', '嘉兴', '湖州', '绍兴',
|
|
|
|
|
'金华', '台州', '芜湖', '蚌埠', '安庆', '阜阳', '九江', '赣州', '吉安', '上饶',
|
|
|
|
|
'淄博', '枣庄', '东营', '潍坊', '济宁', '泰安', '威海', '日照', '临沂', '德州',
|
|
|
|
|
'聊城', '滨州', '菏泽', '洛阳', '平顶山', '安阳', '鹤壁', '新乡', '焦作', '濮阳',
|
|
|
|
|
'许昌', '漯河', '三门峡', '商丘', '信阳', '周口', '驻马店', '黄石', '十堰', '宜昌',
|
|
|
|
|
'襄阳', '鄂州', '荆门', '孝感', '荆州', '黄冈', '咸宁', '随州', '株洲', '湘潭',
|
|
|
|
|
'衡阳', '邵阳', '岳阳', '常德', '张家界', '益阳', '郴州', '永州', '怀化', '娄底',
|
|
|
|
|
'韶关', '珠海', '汕头', '惠州', '江门', '湛江', '茂名', '肇庆', '梅州', '汕尾',
|
|
|
|
|
'河源', '阳江', '清远', '潮州', '揭阳', '云浮', '柳州', '桂林', '梧州', '北海',
|
|
|
|
|
'防城港', '钦州', '贵港', '玉林', '百色', '贺州', '河池', '来宾', '崇左', '三亚',
|
|
|
|
|
'儋州', '五指山', '琼海', '文昌', '万宁', '东方'
|
|
|
|
|
])
|
|
|
|
|
self.city_combo.setFixedWidth(100) # 减小城市选择框宽度使布局更紧凑
|
|
|
|
|
city_layout.addWidget(self.city_combo)
|
|
|
|
|
|
|
|
|
|
city_layout.addStretch()
|
|
|
|
|
|
|
|
|
|
content_layout.addLayout(city_layout)
|
|
|
|
|
|
|
|
|
|
# 按钮区域
|
|
|
|
|
button_layout = QHBoxLayout()
|
|
|
|
|
button_layout.setSpacing(6) # 减小间距使布局更紧凑
|
|
|
|
|
button_layout.setContentsMargins(0, 0, 0, 0)
|
|
|
|
|
self.city_combo.setCurrentText('自动定位')
|
|
|
|
|
self.city_combo.currentTextChanged.connect(self.on_city_changed)
|
|
|
|
|
control_layout.addWidget(self.city_combo)
|
|
|
|
|
|
|
|
|
|
self.refresh_btn = QPushButton("刷新")
|
|
|
|
|
self.refresh_btn.setObjectName("refreshButton")
|
|
|
|
|
self.refresh_btn.setFixedHeight(26) # 减小按钮高度
|
|
|
|
|
button_layout.addWidget(self.refresh_btn)
|
|
|
|
|
self.refresh_btn.setFixedHeight(28)
|
|
|
|
|
control_layout.addWidget(self.refresh_btn)
|
|
|
|
|
|
|
|
|
|
button_layout.addStretch()
|
|
|
|
|
control_layout.addStretch()
|
|
|
|
|
|
|
|
|
|
self.detail_btn = QPushButton("详情")
|
|
|
|
|
self.detail_btn.setObjectName("detailButton")
|
|
|
|
|
self.detail_btn.setFixedHeight(26) # 减小按钮高度
|
|
|
|
|
button_layout.addWidget(self.detail_btn)
|
|
|
|
|
self.detail_btn.setFixedHeight(28)
|
|
|
|
|
control_layout.addWidget(self.detail_btn)
|
|
|
|
|
|
|
|
|
|
content_layout.addLayout(button_layout)
|
|
|
|
|
|
|
|
|
|
# 添加弹性空间
|
|
|
|
|
content_layout.addStretch()
|
|
|
|
|
content_layout.addLayout(control_layout)
|
|
|
|
|
|
|
|
|
|
def setup_connections(self):
|
|
|
|
|
"""设置信号连接"""
|
|
|
|
|
self.close_btn.clicked.connect(self.close_window)
|
|
|
|
|
self.refresh_btn.clicked.connect(self.on_refresh_clicked)
|
|
|
|
|
self.detail_btn.clicked.connect(self.show_detailed_weather)
|
|
|
|
|
self.city_combo.currentTextChanged.connect(self.on_city_changed)
|
|
|
|
|
|
|
|
|
|
def setup_theme(self):
|
|
|
|
|
"""设置主题"""
|
|
|
|
|
@ -208,7 +215,7 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
QFrame#mainFrame {{
|
|
|
|
|
background-color: {colors['surface']};
|
|
|
|
|
border: 1px solid {colors['border']};
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
|
|
|
|
}}
|
|
|
|
|
QLabel {{
|
|
|
|
|
@ -219,27 +226,27 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
}}
|
|
|
|
|
QLabel#temperatureLabel {{
|
|
|
|
|
color: {colors['accent']};
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
padding: 6px 8px;
|
|
|
|
|
margin: 3px;
|
|
|
|
|
padding: 0px 8px;
|
|
|
|
|
margin: 0px 3px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#cityLabel {{
|
|
|
|
|
color: {colors['text_secondary']};
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
padding: 4px 6px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#weatherDescLabel {{
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
padding: 4px 6px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#detailLabel {{
|
|
|
|
|
color: {colors['text_secondary']};
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
padding: 4px 6px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
@ -266,35 +273,12 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 6px 16px;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#refreshButton:hover, QPushButton#detailButton:hover {{
|
|
|
|
|
background-color: {colors['accent_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo {{
|
|
|
|
|
background-color: {colors['surface']};
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
border: 1px solid {colors['border']};
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 4px 7px;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
min-height: 24px;
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo:hover {{
|
|
|
|
|
border-color: {colors['accent']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo::drop-down {{
|
|
|
|
|
border: none;
|
|
|
|
|
width: 14px;
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo::down-arrow {{
|
|
|
|
|
image: none;
|
|
|
|
|
border-left: 2px solid transparent;
|
|
|
|
|
border-right: 2px solid transparent;
|
|
|
|
|
border-top: 5px solid {colors['text']};
|
|
|
|
|
}}
|
|
|
|
|
""")
|
|
|
|
|
else:
|
|
|
|
|
# 浅色主题样式 - 与每日谏言悬浮窗口保持一致
|
|
|
|
|
@ -302,7 +286,7 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
QFrame#mainFrame {{
|
|
|
|
|
background-color: {colors['surface']};
|
|
|
|
|
border: 1px solid {colors['border']};
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
|
|
|
|
|
}}
|
|
|
|
|
QLabel {{
|
|
|
|
|
@ -313,27 +297,27 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
}}
|
|
|
|
|
QLabel#temperatureLabel {{
|
|
|
|
|
color: {colors['accent']};
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-size: 22px;
|
|
|
|
|
font-weight: bold;
|
|
|
|
|
padding: 6px 8px;
|
|
|
|
|
margin: 3px;
|
|
|
|
|
padding: 0px 8px;
|
|
|
|
|
margin: 0px 3px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#cityLabel {{
|
|
|
|
|
color: {colors['text_secondary']};
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
padding: 4px 6px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#weatherDescLabel {{
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-size: 13px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
padding: 4px 6px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
QLabel#detailLabel {{
|
|
|
|
|
color: {colors['text_secondary']};
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
padding: 4px 6px;
|
|
|
|
|
margin: 2px;
|
|
|
|
|
}}
|
|
|
|
|
@ -360,35 +344,12 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
border: none;
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 6px 16px;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
font-size: 12px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
}}
|
|
|
|
|
QPushButton#refreshButton:hover, QPushButton#detailButton:hover {{
|
|
|
|
|
background-color: {colors['accent_hover']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo {{
|
|
|
|
|
background-color: {colors['surface']};
|
|
|
|
|
color: {colors['text']};
|
|
|
|
|
border: 1px solid {colors['border']};
|
|
|
|
|
border-radius: 6px;
|
|
|
|
|
padding: 4px 7px;
|
|
|
|
|
font-size: 11px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
min-height: 24px;
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo:hover {{
|
|
|
|
|
border-color: {colors['accent']};
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo::drop-down {{
|
|
|
|
|
border: none;
|
|
|
|
|
width: 14px;
|
|
|
|
|
}}
|
|
|
|
|
QComboBox#cityCombo::down-arrow {{
|
|
|
|
|
image: none;
|
|
|
|
|
border-left: 2px solid transparent;
|
|
|
|
|
border-right: 2px solid transparent;
|
|
|
|
|
border-top: 5px solid {colors['text']};
|
|
|
|
|
}}
|
|
|
|
|
""")
|
|
|
|
|
|
|
|
|
|
def on_theme_changed(self, is_dark):
|
|
|
|
|
@ -496,12 +457,8 @@ class WeatherFloatingWidget(QDialog):
|
|
|
|
|
|
|
|
|
|
def set_current_city(self, city_name):
|
|
|
|
|
"""设置当前城市"""
|
|
|
|
|
# 阻止信号发射,避免循环调用
|
|
|
|
|
self.city_combo.blockSignals(True)
|
|
|
|
|
index = self.city_combo.findText(city_name)
|
|
|
|
|
if index >= 0:
|
|
|
|
|
self.city_combo.setCurrentIndex(index)
|
|
|
|
|
self.city_combo.blockSignals(False)
|
|
|
|
|
if hasattr(self, 'city_combo'):
|
|
|
|
|
self.city_combo.setCurrentText(city_name)
|
|
|
|
|
|
|
|
|
|
def close_window(self):
|
|
|
|
|
"""关闭窗口 - 只是隐藏而不是销毁"""
|
|
|
|
|
|