该系统实现了获取网站上的天气到本地进行展示的功能,代码如下所示:
mainwindos.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include"weatherData.h"
#include<QNetworkAccessManager>
#include<QAction>
#include<QMenu>
#include<QLineEdit>
#include<QPushButton>
#include<QDateTime>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
protected:
void mousePressEvent(QMouseEvent *event) override; //重写鼠标点击事件函数
void mouseMoveEvent(QMouseEvent *event) override; //重写鼠标移动事件函数
void getWeatherInfo(QString citycode); //获取天气数据
void parseJson(QByteArray& byteArray); //解析JSON数据
void updateWeatherDisplay();
void onSearchBtnClicked();
void refreshWeather();
private slots:
void on_pushButton_quit_clicked(); //关闭UI界面
void onQuitActTriggered(); //菜单被点击后的处理
public slots:
void readHttpReply(QNetworkReply *reply); //新建一个网络请求获取的槽函数
QString getAirQualityColor(const QString& quality);
private:
Ui::MainWindow *ui;
QMenu *quitMenu; //创建一个菜单指针
QAction *quitAct; //定义一个动作
QPoint moffset; //窗口移动时,鼠标与窗口左上角的偏移值
QTimer *refreshTimer;
QNetworkAccessManager *NetAccessManger; //声明一个网络请求对象
bool closePOPWindow(); //关闭窗口的弹窗
Today today; //定义一个今天天气数据对象
Day day[7];
QDateTime lastRefreshTime;
bool isRefreshing = false;
QString currentCityCode;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QJsonArray>
#include <QJsonObject>
#include <QJsonParseError>
#include <QMouseEvent>
#include "weatherData.h"
#include<QMessageBox>
#include<QNetworkReply>
#include<QPushButton>
#include<QLineEdit>
#include<QTimer>
#include<QMessageBox>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowFlag(Qt::FramelessWindowHint);
// 创建带有HTML格式的文本
QString cityHtml = "<html><head><style>"
"body { font-family: 'Microsoft YaHei', sans-serif; margin: 0; }"
"h2 { color: #2c3e50; text-align: center; margin-bottom: 15px; }"
"table { width: 100%; border-collapse: collapse; }"
"th { background-color: #3498db; color: white; padding: 10px; text-align: left; }"
"td { padding: 8px 12px; border-bottom: 1px solid #ecf0f1; }"
"tr:nth-child(even) { background-color: #f9f9f9; }"
"tr:hover { background-color: #f1f9ff; }"
".footer { margin-top: 15px; text-align: center; color: #7f8c8d; font-size: 12px; }"
"</style></head>"
"<body>"
"<h2>主要城市天气预报代码列表</h2>"
"<table>"
"<tr><th>城市</th><th>城市代码</th><th>城市</th><th>城市代码</th></tr>";
// 城市数据对
QVector<QPair<QString, QString>> cities = {
{"北京", "101010100"}, {"上海", "101020100"}, {"天津", "101030100"}, {"重庆", "101040100"},
{"哈尔滨", "101050101"}, {"长春", "101060101"}, {"沈阳", "101070101"}, {"呼和浩特", "101080101"},
{"石家庄", "101090101"}, {"太原", "101100101"}, {"西安", "101110101"}, {"济南", "101120101"},
{"郑州", "101180101"}, {"合肥", "101220101"}, {"南京", "101190101"}, {"杭州", "101210101"},
{"福州", "101230101"}, {"南昌", "101240101"}, {"长沙", "101250101"}, {"武汉", "101200101"},
{"广州", "101280101"}, {"南宁", "101300101"}, {"海口", "101310101"}, {"成都", "101270101"},
{"贵阳", "101260101"}, {"昆明", "101290101"}, {"拉萨", "101140101"}, {"兰州", "101160101"},
{"银川", "101170101"}, {"西宁", "101150101"}, {"乌鲁木齐", "101130101"}, {"台北", "101340101"},
{"香港", "101320101"}, {"澳门", "101330101"}
};
// 组织城市数据到表格(两列布局)
for (int i = 0; i < cities.size(); i += 2) {
cityHtml += "<tr>";
// 第一列城市
cityHtml += QString("<td><b>%1</b></td><td>%2</td>")
.arg(cities[i].first).arg(cities[i].second);
// 第二列城市(如果存在)
if (i + 1 < cities.size()) {
cityHtml += QString("<td><b>%1</b></td><td>%2</td>")
.arg(cities[i+1].first).arg(cities[i+1].second);
} else {
cityHtml += "<td></td><td></td>"; // 空单元格保持对齐
}
cityHtml += "</tr>";
}
cityHtml += "</table>"
"<div class='footer'>数据更新于: " + QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm") + "</div>"
"</body></html>";
// 设置HTML格式文本
ui->textEdit->setHtml(cityHtml);
//每隔三分钟自动刷新一下天气情况
refreshTimer = new QTimer(this);
refreshTimer->setInterval(180000); // 3分钟 = 180,000毫秒
// 连接定时器信号
connect(refreshTimer, &QTimer::timeout, this, [=]() {
refreshWeather();
});
// 启动定时器
refreshTimer->start();
//ui->cityInput->setGeometry(50, 10, 200, 30);
ui->cityInput->setPlaceholderText("输入城市代码 (如:101010100)");
ui->cityInput->setStyleSheet("QLineEdit { background-color: white; border: 1px solid #ccc; border-radius: 5px; padding: 5px; }");
// 查询按钮
//ui->btn_search->setGeometry(260, 10, 80, 30);
ui->btn_search->setText("查询");
ui->btn_search->setStyleSheet("QPushButton { background-color: #4CAF50; color: white; border-radius: 5px; font-size: 14px;}");
//ui->weatherDisplay->setGeometry(50, 50, 300, 30); // 设置位置和大小
ui->weatherDisplay->setReadOnly(true); // 设置为只读
ui->weatherDisplay->setStyleSheet("QLineEdit {"
"background-color: #f0f0f0;"
"border: 1px solid #ccc;"
"border-radius: 5px;"
"padding: 5px;"
"font-size: 14px;"
"}");
// 显示加载状态信息
ui->weatherDisplay->setText("正在获取天气信息,请稍候...");
// QPushButton*btn=new QPushButton(this);
// btn->setText("测试");
// this->setLayout(ui->gridLayoutGlobal); //让界面随着窗口变幻大小
quitMenu = new QMenu(this); //创建一个QMenu对象
quitAct = new QAction(QIcon(":/widget/quit.png"), tr("退出"), this); //定义一个退出动作
quitMenu->addAction(quitAct); //添加动作
// connect(quitMenu,&QMenu::triggered,this,[=]{
// this->close();
// }); //连接信号与槽
connect(quitMenu,&QMenu::triggered,this,&MainWindow::onQuitActTriggered); //连接菜单被触发的信号与槽
NetAccessManger = new QNetworkAccessManager(this); //实例化一个网络请求对象
connect(NetAccessManger,&QNetworkAccessManager::finished,this,&MainWindow::readHttpReply); //连接网络请求获取的信号与槽
//101010100是北京的城市编码
//getWeatherInfo("101010100");
connect(ui->btn_search, &QPushButton::clicked, this, &MainWindow::onSearchBtnClicked);
}
MainWindow::~MainWindow()
{
delete ui;
}
//鼠标点击
void MainWindow::mousePressEvent(QMouseEvent *event)
{
//如果右键被按下
if(event->button() == Qt::RightButton)
{
quitMenu->exec(QCursor::pos()); //在当前鼠标位置显示菜单
}
//当前鼠标位置 event->globalPos()
//当前窗口位置 this->pos()
if(event->button() == Qt::LeftButton)
{
moffset = event->globalPos() - this->pos();
}
}
//鼠标移动
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
this->move(event->globalPos() - moffset); //移动窗口
}
//弹窗
bool MainWindow::closePOPWindow()
{
// 创建一个消息框询问用户是否真的要退出
QMessageBox mes;
mes.setWindowTitle("关闭窗口");
// mes.setWindowFlags(Qt::Drawer); //把标题栏去掉
mes.setIcon(QMessageBox::Warning); //设置一个警告图片
mes.setText("是否关闭窗口?"); //弹窗文本
mes.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); //设置两个按钮
mes.setWindowIcon(QIcon(":/widget/dog.png")); // 设置窗口图标
mes.setButtonText(QMessageBox::Ok, tr("确定")); //ok改为确认
mes.setButtonText(QMessageBox::Cancel, tr("取消")); //Cancel改为取消
// 显示消息框并等待用户交互
int result = mes.exec();
// 根据用户的选择执行相应的操作
if (result == QMessageBox::Ok) {
// 用户选择了确定,关闭主窗口
this->close();
return true;
}
// 用户选择了取消,不关闭主窗口
else
{
return false; // 窗口关闭操作失败
}
}
//右上角退出
void MainWindow::on_pushButton_quit_clicked()
{
closePOPWindow();
}
//鼠标右键退出
void MainWindow::onQuitActTriggered()
{
closePOPWindow();
}
//获取天气数据
void MainWindow::getWeatherInfo(QString citycode)
{
QUrl url("http://t.weather.itboy.net/api/weather/city/" + citycode); //天气数据接口和城市编码
NetAccessManger->get(QNetworkRequest(url)); //发送GET请求,获取数据
}
//解析JSON格式天气数据
void MainWindow::parseJson(QByteArray &byteArray)
{
//错误
QJsonParseError err; //创建一个错误对象
QJsonDocument doc = QJsonDocument::fromJson(byteArray, &err); //将JSON格式解析为QJsonDocument对象
//如果错误
if(err.error != QJsonParseError::NoError)
{
return; //返回
}
QJsonObject rootObj = doc.object(); //创建一个QJsonObject对象返回文档
// qDebug() << rootObj.value("message").toString();
//1.解析城市和日期
today.city = rootObj.value("cityInfo").toObject().value("city").toString(); //城市
today.date = rootObj.value("date").toString(); //日期
//2.解析昨天yesterday数据
QJsonObject objData = rootObj.value("data").toObject(); //获取data对象
QJsonObject objYesterday = objData.value("yesterday").toObject(); //昨天
day[0].week = objYesterday.value("week").toString(); //星期
day[0].date = objYesterday.value("date").toString(); //日期
day[0].weatherType = objYesterday.value("type").toString(); //天气类型
QString highT; //最高温
highT = objYesterday.value("high").toString().split(" ").at(1); //空格分割,取分割后第二个数据,1是第二个,0是第一个
day[0].highTem = highT.left(highT.length() - 1).toInt(); //把℃减掉,只剩数字
QString lowT; //最低温
lowT = objYesterday.value("low").toString().split(" ").at(1);
day[0].lowTem = lowT.left(lowT.length() - 1).toInt();
//风的类型,风力
day[0].windType = objYesterday.value("fx").toString(); //风的类型
day[0].windPower = objYesterday.value("fl").toString(); //风力
//空气指数
day[0].airQuality =objYesterday.value("aqi").toDouble(); //空气质量
//3.解析未来几天的天气数据
QJsonArray forecastArray = objData.value("forecast").toArray(); //获取forecast数组
//遍历未来几天天气数据
for(int i=0 ; i<6 ; i++)
{
QJsonObject forecastObj = forecastArray[i].toObject(); //获取JSON对象
day[i+1].week = forecastObj.value("week").toString(); //星期
day[i+1].date = forecastObj.value("ymd").toString(); //日期
day[i+1].weatherType = forecastObj.value("type").toString(); //天气类型
//空气指数
day[i+1].airQuality =forecastObj.value("aqi").toDouble(); //空气质量
QString highT; //最高温
highT = forecastObj.value("high").toString().split(" ").at(1); //空格分割,取分割后第二个数据,1是第二个,0是第一个
day[i+1].highTem = highT.left(highT.length() - 1).toInt(); //把℃减掉,只剩数字
QString lowS; //最低温
lowS = forecastObj.value("low").toString().split(" ").at(1);
day[i+1].lowTem = lowS.left(lowS.length() - 1).toInt();
//风的类型,风力
day[i+1].windType = forecastObj.value("fx").toString(); //风的类型
day[i+1].windPower = forecastObj.value("fl").toString(); //风力
//4、解析今天的数据
today.Temperature =objData.value("wendu").toInt(); //温度
today.ganMao =objData.value("ganmao").toString(); //感冒指数
today.Humidity = objData.value("shidu").toString(); //湿度
today.PM25 = objData.value("pm25").toDouble(); //PM2.5
today.airQuality = objData.value("quality").toString(); //空气质量
//5、forecast里面也有今天的数据
today.weatherType = day[1].weatherType; //天气类型
today.highTem = day[1].highTem; //最高温
today.lowTem = day[1].lowTem; //最低温
today.windType = day[1].windType; //风的类型
today.windPower = day[1].windPower; //风力
}
updateWeatherDisplay();
}
//网络请求获取
void MainWindow::readHttpReply(QNetworkReply *reply)
{
int status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); //状态码
//请求错误
if(reply->error() != QNetworkReply::NoError || status_code != 200)
{
qDebug() << reply->errorString().toLatin1().data(); //打印错误信息
QMessageBox::warning(this,"天气","请求数据失败", QMessageBox::Ok); //弹出警告信息框
}
//请求成功
else
{
QByteArray byteArray = reply->readAll(); //读取服务器数据
qDebug() << "read all:"<< byteArray.data(); //打印接收到的数据
parseJson(byteArray); //解析JSON数据
}
reply->deleteLater(); //释放对象
}
void MainWindow::updateWeatherDisplay()
{
QDateTime nextRefresh = lastRefreshTime.addMSecs(refreshTimer->interval());
QString weatherInfo = QString(
"🌆 %1 | 🕒 %2更新 | 🌡️ %3℃ | ☁️ %4 | "
"⬇️ %5℃ | ⬆️ %6℃ | 💨 %7 | "
"🍃 %8"
)
.arg(today.city)
.arg(lastRefreshTime.toString("hh:mm"))
.arg(today.Temperature)
.arg(today.weatherType)
.arg(today.lowTem)
.arg(today.highTem)
.arg(today.windPower)
.arg(today.airQuality);
// 设置文本
ui->weatherDisplay->setText(weatherInfo);
// 设置样式表 - 根据空气质量变化背景色
QString style = "QLineEdit {"
"background-color: %1;"
"border: 2px solid #3498db;"
"border-radius: 15px;"
"padding: 10px 15px;"
"font-size: 14px;"
"font-weight: bold;"
"color: #2c3e50;"
"}";
if (today.airQuality == "优") {
ui->weatherDisplay->setStyleSheet(style.arg("#d5f5e3")); // 浅绿色
} else if (today.airQuality == "良") {
ui->weatherDisplay->setStyleSheet(style.arg("#fef9e7")); // 浅黄色
} else if (today.airQuality == "轻度污染") {
ui->weatherDisplay->setStyleSheet(style.arg("#fdebd0")); // 浅橙色
} else {
ui->weatherDisplay->setStyleSheet(style.arg("#fadbd8")); // 浅红色
}
// 添加提示文本
ui->weatherDisplay->setPlaceholderText("输入城市代码查询天气");
// 设置对齐方式
ui->weatherDisplay->setAlignment(Qt::AlignCenter);
// 添加悬停效果
ui->weatherDisplay->setStyleSheet(ui->weatherDisplay->styleSheet() +
"QLineEdit:hover {"
" background-color: #eaf2f8;"
" border: 2px solid #2980b9;"
"}");
// 添加焦点效果
ui->weatherDisplay->setStyleSheet(ui->weatherDisplay->styleSheet() +
"QLineEdit:focus {"
" background-color: #ffffff;"
" border: 2px solid #3498db;"
"}");
}
void MainWindow::refreshWeather()
{
// 如果正在刷新,则跳过
if (isRefreshing) {
return;
}
isRefreshing = true;
// 显示刷新状态
ui->weatherDisplay->setText("正在刷新天气数据...");
// 记录刷新时间
lastRefreshTime = QDateTime::currentDateTime();
// 获取天气信息
getWeatherInfo(currentCityCode);
// 在 readHttpReply 中重置刷新状态
}
void MainWindow::onSearchBtnClicked()
{
getWeatherInfo(ui->cityInput->text());
}
QString MainWindow::getAirQualityColor(const QString& quality)
{
if (quality == "优") {
return "#2ecc71"; // 绿色
} else if (quality == "良") {
return "#f1c40f"; // 黄色
} else if (quality == "轻度污染") {
return "#e67e22"; // 橙色
} else if (quality == "中度污染" || quality == "重度污染" || quality == "严重污染") {
return "#e74c3c"; // 红色
} else {
return "#95a5a6"; // 默认灰色
}
}
weatherData.h
#ifndef WEATHERDATA_H
#define WEATHERDATA_H
#include <QString>
//今天的数据类
class Today{
public:
Today()
{
city ="广州"; //城市
date ="2025-1-10"; //日期
weatherType ="多云"; //天气类型
highTem = 30; //最高温
lowTem = 18; //最低温
ganMao ="感冒指数"; //感冒指数
Temperature = 0; //温度
Humidity = "0%"; //湿度
PM25 = 0; //PM2.5
windType ="南风"; //风的类型
windPower ="2级"; //风力
airQuality ="无数据"; //空气质量
}
public:
QString city;
QString date;
int Temperature;
QString weatherType;
int highTem;
int lowTem;
QString ganMao;
QString Humidity;
int PM25;
QString windType;
QString windPower;
QString airQuality;
};
//未来几天的数据类
class Day{
public:
Day()
{
week ="周五"; //星期
date ="2023-7-29"; //日期
weatherType ="多云"; //天气类型
airQuality = 0; //空气指数,优 //空气质量
highTem = 0; //最高温
lowTem = 0; //最低温
windType ="南风"; //风的类型
windPower ="2级"; //风力
}
QString week;
QString date;
QString weatherType;
int airQuality;
int highTem;
int lowTem;
QString windType;
QString windPower;
};
#endif // WEATHERDATA_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}