项目介绍
本项目基于QT平台开发的一款天气预报的应用,效果图如下:
1、 有城市的天气预报,有背景图、控件半透明化。
2、 显示日期,城市名称,当天的天气预报
3、 当天天气预报的详细数据
4、 该天的一些生活指数:如感冒指数、每日寄语
5、 当天的日出日落时间,及扇形时间占比
6、 该城市,前一后四天的天气预报,含有日期,星期,天气,高低温
7、 最近一周的温湿度曲线
8、 搜索框、刷新按钮。
9、 窗口大小固定,无最大、最小化、关闭按钮。鼠标拖动窗口移动,右键退出,背景音乐。
10、自定义按钮图标
实现思路
实现过程
- 鼠标拖动窗口
mouseMoveEvent是鼠标移动的操作事件,mousePressEvent是按下鼠标的事件。添加私有成员:mPos做鼠标按下事件的坐标点记录(需要头文件:#include )
globalPos()获取鼠标在窗口的全局坐标,也可以理解为屏幕上的坐标。而pos()获取到的是应用程序窗体的坐标。要移动窗口操作的是程序相对屏幕原点的的坐标,用当前鼠标按下得到的屏幕坐标减去程序坐标,得到就是程序相对屏幕的一个坐标。
void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event);
//窗口移动计算
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
move(event->globalPos()-mPos);
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
mPos=event->globalPos()-this->pos();
}
- 读取城市Json文件
读取citycode-2019-08-23.json里面所有的内容,将所有的城市名称和城市id保存在一个map当中。<”城市”,“City_Code”>,这样就可以通过城市名称直接得到城市的code了。citycode-2019-08-23.json是一个Json文件,那么我们需要用到QJson来读取和解析
//将解析到的城市都存在这个map中
std::map<QString,QString>m_mapCity2Code;
//获取当前程序运行的路径
QString fileName = QCoreApplication::applicationDirPath();
//创建错误信息收集的对象
QJsonParseError err;
//构建文件所在的路径。因为citycode-2019-08-23.json,在项目文件夹下
//也可以将它复制到项目运行的目录下,就不需要这么先返回两级目录
fileName+="/citycode-2019-08-23.json";
QFile file(fileName);
//打开文件
file.open(QIODevice::ReadOnly|QIODevice::Text);//只读用文本的方式读取
QByteArray json = file.readAll();
file.close();
//读取Json数据并用fromJson将文本格式转换为QJsonDocument
QJsonDocument jsonDoc = QJsonDocument::fromJson(json,&err);
//获取城市列表数组
QJsonArray citys = jsonDoc.array();//转换成array类型
for(int i=0;i<citys.size();i++)
{
QString code = citys.at(i).toObject().value("city_code").toString();
QString city = citys.at(i).toObject().value("city_name").toString();
//省份的code是空的,所以城市代码长度大于0的都可以添加的map中
if(code.size()>0)
m_mapCity2Code.insert(std::pair<QString,QString>(city,code));
}
}
//重载操作符[“city”]。根据城市名称直接得到城市代码:
QString operator[](const QString& city)
{
//为了很好的匹配,设置了直接搜索城市名字
std::map<QString,QString>::iterator it = m_mapCity2Code.find(city);
if(it==m_mapCity2Code.end()){
//搜索城市后戴市字
it = m_mapCity2Code.find(city+"市");
}
if(it==m_mapCity2Code.end()){
//搜索城市名后带县字
it = m_mapCity2Code.find(city+"县");
}
if(it!=m_mapCity2Code.end())
//找到直接返回城市代码
return it->second;
//没找到返回9个0
return "000000000";
- 请求天气API数据
原理:使用QNetworkAccessManager从网上get对应的数据
// 请求天气API信息
url = "http://t.weather.itboy.net/api/weather/city/"; //天气预报请求api
city = u8"长沙";//默认访问的城市
cityTmp = city;//临时存放城市变量,防止输入错误城市的时候,原来的城市名称还在。
manager = new QNetworkAccessManager(this);//new的一个QNetworkAccessManager对象
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replayFinished(QNetworkReply*)));
getWeatherInfo(manager);
//为了便于后面的刷新,和切换城市,请求数据是需要重复执行的,所以我们将请求数据的部分封装成函数,便于后面使用
//请求数据
//只要[ ]操作得到的不是0代码的城市,就将代码加到url的后面,然后使用QNetworkAccessManager对象manager来get天气预报数据,到这里,只是发送了一个get请求,到底说明时候结束,我们这里不管。后续的事情,当信请求结束的清号产生之后,让槽函数去做。
void MainWindow::getWeatherInfo(QNetworkAccessManager *manager)
{
QString citycode = tool[city];
if(citycode=="000000000"){
QMessageBox::warning(this, u8"错误", u8"天气:指定城市不存在!", QMessageBox::Ok);
return;
}
QUrl jsonUrl(url + citycode);
manager->get( QNetworkRequest(jsonUrl) );
}
void MainWindow::replayFinished(QNetworkReply *reply)
{
/* 获取响应的信息,状态码为200表示正常 */
//reply是一个应答。在这里,需要应答是没有错误,和状态码正常:200,说明请求很顺利。
QVariant status_code = reply->attribute(QNetworkRequest::HttpStatusCodeAttr