功能
获取当前网络下对应区县的实时温度、天气、地址、空气质量、24小时天气预测,QT环境5.15.2,地理限制,均使用国内API,国外是否支持需要查询对应文档。
开源代码链接
基于Qt的天气显示小控件
后续会不定时更新UI库资源
运行时UI展示


Click_weather
功能实现
数据获取
- 通过访问“http://myip.ipip.net”网站获取公网IP。
- 经纬度API为百度地图普通IP定位API,通过公网IP获取所在区县经纬度
- 天气API为和风天气API,获取实时天气、实时空气资料、24h天气预测
数据显示
基本都是Label显示,24h控件由水平布局HBoxLayout,数据向内部item写入,并添加触摸和鼠标支持。
素材
素材主要为各种天气图标,来源于阿里巴巴矢量图标库和豆包生成,有些经过细微的修改。仓库中包含每个图标对应的ps文件,png文件,如果是夜间图标,也包含对应的ai文件。
UI风格参考
参考VIVO ,Origin系统桌面天气原子组件,其24h温度是曲线实现,暂时没有头绪,简化一下直接由数字实现

资源文件索引
每种天气对应哪个素材由和风天气API获取,回传数据中有一个“icon”参数,就是对应的和风天气素材库对应图标的号码,我们在资源文件中的名称也参考这个号码。
应用实现
数据获取步骤
获取公网IP
向 http://myip.ipip.net 发送请求,回传数据中包含当前设备的公网IP
此数据只有百度API获取当前IP所在区的经纬度有用

获取经纬度
向百度地图,普通IP定位 API发送请求,传入参数为,之前获取的IP地址、API 的AK码、经纬度坐标系格式为gcj02,而不是百度默认的经纬度坐标系。
此步骤主要获取x和y,分别为经度和维度,为后续获取天气信息

获取实时天气
向和风天气-实时天气API,发送请求,传入参数为API_Host,经纬度,API_Key。
获取的信息中主要使用temp、icon、text。

获取实时空气质量
向和风天气-实时空气质量API发送请求,传入参数和之前一样
主要使用category参数

获取24h天气预测
向和风天气-按小时预测API发送请求,传入参数和之前一样
主要使用fxTime,temp,icon, 分别作为24h预测中时间、图标索引、温度

代码框架
Click
主函数Clic类,主要实现各种控件的初始化内容,以及各API回传数据槽函数。
Click.cpp
#include "click.h"
#include <QLabel>
#include <QSslSocket>
#include <QFile>
#include <QPainter>
#include <QPalette>
#include <QJsonArray>
/* ------------------------Click---------------------------- */
Click::Click(QWidget *parent)
: QMainWindow(parent)
{
vWidthRatio = 1.0;
hHeightRatio = 1.0;
this->setGeometry(0, 0, 900 * hHeightRatio, 300 * vWidthRatio);
this->setStyleSheet("background-color: rgb(193, 193, 193);");
weatherAPI = new WeatherAPI(); // 初始化天气API类
checker = new IPChecker(); // 初始化经纬度获取类
initWeathrUI();
// 初始化定时器
autoRefreshTimer = new QTimer(this);
connect(autoRefreshTimer, &QTimer::timeout, this, &Click::refreshData);
// 设置1小时刷新一次(3600000毫秒)
autoRefreshTimer->start(3600000);
connect(weatherAPI, &WeatherAPI::weatherDataReceived, this, &Click::updateRealTimeWeather);
connect(checker, &IPChecker::errorOccurred, this, &Click::IPCheckerror);
connect(checker, &IPChecker::locationReceived, this, &Click::locationChecked);
connect(checker, &IPChecker::coordinateReceived, this, &Click::coordinateChecked);
connect(weatherAPI, &WeatherAPI::airQualityDataReceived, this, &Click::airQualityChecked);
connect(weatherAPI, &WeatherAPI::hourlyWeatherDataReceived, this, &Click::hourlyWeatherChecked);
}
Click::~Click() {
}
//
/**
* @brief 初始化天气UI
*/
void Click::initWeathrUI(){
QPalette whiteColor;
whiteColor.setColor(QPalette::WindowText, Qt::white);
// 天气显示区域
weatherDisplayWidget = new QWidget(this);
weatherDisplayWidget->setGeometry(10 * hHeightRatio, 10 * vWidthRatio, 886 * hHeightRatio, 270 * vWidthRatio);
weatherDisplayWidget->setStyleSheet("background-color: rgb(255, 255, 255); border-radius: 20px;");
//左侧当前天气ICON
weatherIcon = new QLabel(weatherDisplayWidget);
weatherIcon->setGeometry(40 * hHeightRatio, 35 * vWidthRatio, 200 * hHeightRatio, 200 * vWidthRatio);
weatherIcon->setAlignment(Qt::AlignCenter);
//右侧天气信息
QWidget *weatherInfoWidget = new QWidget(weatherDisplayWidget);
weatherInfoWidget->setGeometry(280 * hHeightRatio, 35 * vWidthRatio, 566 * hHeightRatio, 200 * vWidthRatio);
//天气背景图
weatherBackgroundPic = new QLabel(weatherInfoWidget);
weatherBackgroundPic->setGeometry(0 * hHeightRatio, 0 * vWidthRatio, 566 * hHeightRatio, 200 * vWidthRatio);
weatherBackgroundPic->setScaledContents(true);
weatherBackgroundPic->setStyleSheet("border-radius: 10px;");
//温度
tempLabel = new QLabel(weatherInfoWidget);
tempLabel->setGeometry(15 * hHeightRatio, 8 * vWidthRatio, 70 * hHeightRatio, 55 * vWidthRatio);
tempLabel->setFont(QFont("黑体", 38));
tempLabel->setText("");
tempLabel->setStyleSheet("background: transparent;font-weight: bold;");
tempLabel->setPalette(whiteColor);
//摄氏度
QLabel *tempSignLabel = new QLabel(weatherInfoWidget);
tempSignLabel->setGeometry(82 * hHeightRatio, 11 * vWidthRatio, 20 * hHeightRatio, 20 * vWidthRatio);
tempSignLabel->setFont(QFont("黑体", 10));
tempSignLabel->setText("℃");
tempSignLabel->setStyleSheet("background: transparent;");
tempSignLabel->setPalette(whiteColor);
//天气状况
conditionLabel = new QLabel(weatherInfoWidget);
conditionLabel->setGeometry(82 * hHeightRatio, 34 * vWidthRatio, 100 * hHeightRatio, 24 * vWidthRatio);
conditionLabel->setFont(QFont("黑体", 15));
conditionLabel->setText("");
conditionLabel->setStyleSheet("background: transparent;");
conditionLabel->setPalette(whiteColor);
//空气质量
airQualityLabel = new QLabel(weatherInfoWidget);
airQualityLabel->setGeometry(430 * hHeightRatio, 13 * vWidthRatio, 120 * hHeightRatio, 24 * vWidthRatio);
airQualityLabel->setFont(QFont("黑体", 15));
airQualityLabel->setText("");
airQualityLabel->setStyleSheet("background: transparent;");
airQualityLabel->setPalette(whiteColor);
airQualityLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
//地址
addressLabel = new QLabel(weatherInfoWidget);
addressLabel->setGeometry(490 * hHeightRatio, 40 * vWidthRatio, 60 * hHeightRatio, 20 * vWidthRatio);
addressLabel->setFont(QFont("黑体", 11));
addressLabel->setText("");
addressLabel->setStyleSheet("background: transparent;");
addressLabel->setPalette(whiteColor);
//地址图标
QString locationIconPath = ":/icons/location.png";
if(QFile::exists(locationIconPath)){
QPixmap locationIcon(locationIconPath);
locationIcon = locationIcon.scaled(15 * hHeightRatio, 15 * vWidthRatio, Qt::KeepAspectRatio, Qt::SmoothTransformation);
QLabel *locationIconLabel = new QLabel(weatherInfoWidget);
locationIconLabel->setGeometry(470 * hHeightRatio, 43 * vWidthRatio, 15 * hHeightRatio, 15 * vWidthRatio);
locationIconLabel->setPixmap(locationIcon);
locationIconLabel->setAlignment(Qt::AlignVCenter);
locationIconLabel->setStyleSheet("background: transparent;");
}
//24小时天气预测
QWidget *dailyWeatherForecastWidget = new QWidget(weatherInfoWidget);
dailyWeatherForecastWidget->setGeometry(18 * hHeightRatio, 68 * vWidthRatio, 530 * hHeightRatio, 120 * vWidthRatio);
dailyWeatherForecastWidget->setStyleSheet("background-color: rgba(255, 255, 255, 0.1); border-radius: 20px;");
// 创建滚动区域用于显示小时天气预报
hourlyScrollArea = new HourlyWeatherScrollArea(dailyWeatherForecastWidget);
hourlyScrollArea->setGeometry(0 * hHeightRatio, 0 * vWidthRatio,
530 * hHeightRatio, 120 * vWidthRatio);
hourlyScrollArea->setRatios(vWidthRatio, hHeightRatio);
//创建加载图标
loadingIcon = new LoadingIcon(weatherDisplayWidget);
loadingIcon->setGeometry(10 * hHeightRatio, 10 * vWidthRatio, 40 * hHeightRatio, 40 * vWidthRatio);
// 连接按钮点击信号
connect(loadingIcon->getButton(), &QPushButton::clicked, this, [this](){
loadingIcon->startRotation(); // 点击时开始旋转
refreshData();



被折叠的 条评论
为什么被折叠?



