嵌入式图形界面设计报告班级:计算机科学与技术15-2班小组成员:刘航征、安宝、曲晗羽杨祎涵、张振、李雪辰2017年12月一、前言天气预报(测)或气象预报(测)是使用现代科学技术对未来某一地点地球大气层的状态进行预测。
从史前人类就已经开始对天气进行预测来相应地安排其工作与生活(比如农业生产、军事行动等等)。
今天的天气预报主要是使用收集大量的数据(气温、湿度、风向和风速、气压等等),然后使用目前对大气过程的认识(气象学)来确定未来空气变化。
由于大气过程的混乱以及今天科学并没有最终透彻地了解大气过程,因此天气预报总是有一定误差的。
最传统的数据是在地面或海面上通过专业人员、爱好者、自动气象站或者浮标收集的气压、气温、风速、风向、湿度等数据。
世界气象组织协调这些数据采集的时间,并制定标准。
这些测量分每小时一次(METAR)或者每六小时一次(SYNOP)。
该项目为一款天气预报软件,基于Qt5开发,具有查询指定城市天气、显示当天天气状况以及未来四天天气大致状况的主要功能,次要功能为更换软件皮肤,显示当天感冒指数等功能。
软件预览图:二、选用的技术基本说明1、Qt JSON操作QJsonDocumentQJsonDocument 类用于读和写JSON 文档。
一个JSON 文档可以使用QJsonDocument::fromJson() 从基于文本的表示转化为QJsonDocument,toJson() 则可以反向转化为文本。
解析器非常快且高效,并将JSON 转换为Qt 使用的二进制表示。
已解析文档的有效性,可以使用!isNull() 进行查询。
如果要查询一个JSON 文档是否包含一个数组或一个对象,使用isArray() 和isObject()。
包含在文档中的数组或对象可以使用array() 或object() 检索,然后读取或操作。
也可以使用fromBinaryData() 或fromRawData() 从存储的二进制表示创建来JSON 文档。
QJsonArrayQJsonArray 类封装了一个JSON 数组。
JSON 数组是值的列表。
列表可以被操作,通过从数组中插入和删除QJsonValue 。
一个QJsonArray 可以和一个QVariantList 相互转换。
可以使用size() 来查询条目的数量,通过insert() 在指定索引处插入值,removeAt() 来删除指定索引的值。
QJsonObjectQJsonObject 类封装了一个JSON 对象。
一个JSON 对象是一个“key/value 对”列表,key 是独一无二的字符串,value 由一个QJsonValue 表示。
一个QJsonObject 可以和一个QVariantMap 相互转换。
可以使用size() 来查询“key/value 对”的数量,通过insert() 插入“key/value 对”,remove() 删除指定的key。
QJsonValueQJsonValue 类封装了一个值。
JSON 中的值有6 种基本数据类型:∙bool(QJsonValue::Bool)∙double(QJsonValue::Double)∙string(QJsonValue::String)∙array(QJsonValue::Array)∙object(QJsonValue::Object)∙null(QJsonValue::Null)一个值可以由任何上述数据类型表示。
此外,QJsonValue 有一个特殊的标记来表示未定义的值,可以使用isUndefined() 查询。
值的类型可以通过type() 或isBool()、isString() 等访问函数查询。
同样地,值可以通过toBool()、toString() 等函数转化成相应的存储类型。
QJsonParseErrorQJsonParseError 类用于在JSON 解析中报告错误。
枚举QJsonParseError::ParseError:该枚举描述JSON 文档在解析过程中所发生的错误类型。
2、Qt XML 操作QXmlStreamReader用于读取格式良好的XML文档的快速解析器,该类最快且最易于使用,并提供了与其他Qt兼容的应用程序编程接口,很适用于编写单通道解析器;3、QNetworkAccessManagerQNetworkAccessManager类允许应用程序发送网络请求和接收网络应答。
三、方案设计1、初始化UI界面2、获取当前地区时间3、从文件中读取每个城市名称以及其代码,将其组合分别存入QMap类对象citykeys中4、用预设的url发送http请求,获取本地城市名称5,、用获取的本地城市名称获取citykeys中对应的城市代码发出查询未来五天天气的http请求6、收到的回复为JSON文档,用QJsonDocument类解析JSON文档,将得到的未来五天的天气信息分别存入Forecast结构体数组forecast的每一个元素中,将这些信息显示在主窗口中对应的控件上,然后发出查询今天天气的http请求7、收到的回复为XML格式文档,用QXmlStreamReader类读取其信息,将当天的天气信息存入Today 结构体today中,将这些信息显示在主窗口中对应的控件上。
8、设置搜索按钮以及换肤按钮的信号与槽的关联。
流程图四、详细代码解析ui设计界面:mainwindow.h:#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include<QNetworkAccessManager> #include<QNetworkReply>#include<QNetworkRequest>#include<QPixmap>#include<QPaintEvent>#include<QPainter>#include<QPoint>#include<QMouseEvent>#include<QLabel>namespace Ui {class MainWindow;}struct Forecast{QString fengxiang;QString fengli;QString high;QString type;QString low;QString date;};struct Today{QString ganmao;QString city;QString updatetime;QString wendu;QString fengli;QString fengxiang;QString sunrise;QString sunset;QString shidu;};class MainWindow : public QMainWindow{Q_OBJECTpublic:explicit MainWindow(QWidget *parent = 0); ~MainWindow();protected:void paintEvent(QPaintEvent *);void mousePressEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event);void mouseReleaseEvent(QMouseEvent *); protected slots:void replayFinished(QNetworkReply *reply);private slots:void on_getButton_clicked();void on_updateButton_clicked();private:Ui::MainWindow *ui;QNetworkAccessManager *manager;QString URL_1;QString URL_2;Forecast forecast[5];Today today;void parseJson(QString Json);void parseXml(QString Xml);void parseCity(QString City);void loadCitykeys();//加载城市代码文件QMap<QString,QString> citykeys;//存储城市代码int choose;//0.查询IP 1.今天天气+指数2.未来5天天气QPixmap pixmap;QPoint move_point;bool mouse_press;QList<QLabel *> forecast_date_list;QList<QLabel *> forecast_temp_list;QList<QLabel *> forecast_type_list;QString city;int uid;};#endif //MAINWINDOW_Hmainwindow.cpp:#include "mainwindow.h"#include "ui_mainwindow.h"#include<QVariant>#include<QByteArray>#include<QJsonParseError>#include<QJsonArray>#include<QJsonObject>#include<QJsonDocument>#include<QJsonValue>#include<QXmlStreamReader>#include<QMessageBox>//#include<QDebug>MainWindow::MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow){ui->setupUi(this);setWindowFlags(Qt::FramelessWindowHint);setAttribute(Qt::WA_TranslucentBackground);pixmap.load(":/images/UI0");resize(pixmap.size());uid = 0;mouse_press = false;forecast_date_list<<ui->forecast_0_date<<ui->forecast_1_date<<ui->forecast_2_date<<ui->forecast_3_date<<ui->forecast_4_date;forecast_temp_list<<ui->forecast_0_temp<<ui->forecast_1_temp<<ui->forecast_2_temp<<ui->forecast_3_temp<<ui->forecast_4_temp;forecast_type_list<<ui->forecast_0_type<<ui->forecast_1_type<<ui->forecast_2_type<<ui->forecast_3_type<<ui->forecast_4_type;manager = new QNetworkAccessManager(this);//天气APIURL_1 = "/weather_mini?citykey=";URL_2 = "/WeatherApi?citykey=";connect(manager,SIGNAL(finished(QNetworkReply*)),this,SLOT(replayFinished(QN etworkReply*)));//设置组件样式ui->cityEdit->setTextMargins(0, 0, ui->getButton->width(), 0);ui->cityEdit->setStyleSheet("QLineEdit{border: 1px solid gray;border-radius: 3px;background:rgb(200, 231, 232);}QLineEdit:hover{border-color:transparent; }");ui->getButton ->setStyleSheet("background:transparent;");ui->closeButton->setStyleSheet("QPushButton{border-image:url(:/images/close);}QPushButton:hover{border-image:url(:/images/close_on);}QPushButton:hover:pressed{border-image:url(:/images/close);}");ui->minButton->setStyleSheet("QPushButton{border-image:url(:/images/min);}QPushButton:hover{border-image:url(:/images/min_on);}QPushButton:hover:pressed{border-image:url(:/images/min);}");ui->updateButton->setStyleSheet("QPushButton{border-image:url(:/images/update);}QPushButton:hover{border-image:url(:/ima ges/update_on);}QPushButton:hover:pressed{border-image:url(:/images/update); }");QDateTime time = QDateTime::currentDateTime();ui->date->setText(tr("%1").arg(time.toString("yyyy-MM-dd")));//加载城市代码loadCitykeys();//启动程序后先查询ip定位默认城市choose = 0;manager->get(QNetworkRequest(QUrl("/iplookup/ipl ookup.php")));}MainWindow::~MainWindow(){delete ui;}void MainWindow::paintEvent(QPaintEvent *){QPainter painter(this);painter.drawPixmap(0, 0, pixmap);//绘制UI}void MainWindow::mousePressEvent(QMouseEvent *event){if(event->button() == Qt::LeftButton){//鼠标相对于窗体的位置)move_point = event->pos();mouse_press = true;}}void MainWindow::mouseMoveEvent(QMouseEvent *event){if(mouse_press){//鼠标相对于屏幕的位置QPoint move_pos = event->globalPos();//移动主窗体this->move(move_pos - move_point);}}void MainWindow::mouseReleaseEvent(QMouseEvent *){mouse_press = false;}void MainWindow::loadCitykeys() {QFile file(":/citykeys/citykeys");if ( !file.open(QIODevice::ReadOnly | QIODevice::Text) ) return ;QString tmp;while (file.atEnd() == 0) {tmp = file.readAll();}QStringList list = tmp.split(",");for(int i = 0; i < list.length(); i++) {QString s = list.at(i);QString citys = s.split(":").at(1);QString city = citys.replace("\"", "");QString codes = s.split(":").at(0);QString code = codes.replace("\"", "");citykeys.insert(city, code);}}void MainWindow::replayFinished(QNetworkReply *reply){QVariant status_code =reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);if(reply->error() == QNetworkReply::NoError){QByteArray bytes = reply->readAll();if(choose == 0)//查询IP{QString result = QString::fromLocal8Bit(bytes);parseCity(result);}else if(choose == 1)//今天天气+指数{QString result(bytes);parseXml(result);}else if(choose == 2)//未来5天天气{QString result(bytes);parseJson(result);}}elseQMessageBox::information(this,tr("出错啦"),tr("网络错误,请检查网络连接"),QMessageBox::Ok,QMessageBox::Ok);}//解析城市信息void MainWindow::parseCity(QString City){city = City.split(tr(" ")).at(5);if(city == "" || citykeys[city]==""){QMessageBox::information(this,tr("提示"),tr("无法定位城市,请手动查询"),QMessageBox::Ok,QMessageBox::Ok);return;}QString url = URL_1 + citykeys[city];choose = 2;manager->get(QNetworkRequest(QUrl(url)));}//解析json格式的未来天气void MainWindow::parseJson(QString Json){QByteArray byte_array;QJsonParseError json_error;QJsonDocument parse_doucment =QJsonDocument::fromJson(byte_array.append(Json),&json_error);if(json_error.error == QJsonParseError::NoError){QJsonObject obj = parse_doucment.object();QJsonValue desc = obj.take("desc");if(desc.toString() != "OK"){QMessageBox::information(this,tr("抱歉"),tr("暂无此城市的天气情况"),QMessageBox::Ok,QMessageBox::Ok);return;}QJsonValue data = obj.take("data");today.ganmao = data.toObject().take("ganmao").toString();QJsonValue forecast1 = data.toObject().take("forecast");QJsonArray forecast2 = forecast1.toArray();for(int i=0; i<5; i++){QJsonValue value = forecast2.at(i);QJsonObject object = value.toObject();forecast[i].fengxiang = object.take("fengxiang").toString();forecast[i].date = object.take("date").toString();forecast[i].fengli = object.take("fengli").toString();forecast[i].high = object.take("high").toString();forecast[i].low = object.take("low").toString();forecast[i].type = object.take("type").toString();}for(int i=0;i<5;i++){forecast_date_list[i]->setText(tr("%1").arg(forecast[i].date));forecast_temp_list[i]->setText(tr("%1- %2").arg(forecast[i].low.split(" ").at(1)).arg(forecast[i].high.split(" ").at(1)));forecast_type_list[i]->setPixmap(QPixmap(tr(":/images/%1").arg(forecast[i].t ype)));forecast_type_list[i]->setToolTip(tr("%1 : %2- %3").arg(forecast[i].type).arg(forecast[i].fengli).arg(forecast[i].fengxia ng));}ui->forecast_0_date->setText(tr("今天"));QString url = URL_2 + citykeys[city];choose = 1;manager->get(QNetworkRequest(QUrl(url)));}else{QMessageBox::information(this,tr("出错啦"),tr("数据出错,请重试"),QMessageBox::Ok,QMessageBox::Ok);return;}}//解析XML格式的今天天气void MainWindow::parseXml(QString Xml){QXmlStreamReader xml(Xml);while(!xml.atEnd()){if(xml.hasError()){QMessageBox::information(this,tr("出错啦"),tr("数据出错,请重试"),QMessageBox::Ok,QMessageBox::Ok);return;}else if(xml.isStartElement()){if(()=="city"){today.city = xml.readElementText();}else if(()=="updatetime"){today.updatetime = xml.readElementText();}else if(()=="wendu"){today.wendu = xml.readElementText();}else if(()=="fengli"){today.fengli = xml.readElementText();}else if(()=="shidu"){today.shidu = xml.readElementText();}else if(()=="fengxiang"){today.fengxiang = xml.readElementText();}else if(()=="sunrise_1"){today.sunrise = xml.readElementText();}else if(()=="sunset_1"){today.sunset = xml.readElementText();xml.clear();ui->city->setText(tr("%1").arg(today.city));ui->temp->setText(tr("%1℃").arg(today.wendu));ui->sunrise->setText(tr("%1").arg(today.sunrise));ui->sunset->setText(tr("%1").arg(today.sunset));ui->label->setText(tr("日出"));ui->label_2->setText(tr("日落"));ui->label_3->setText(tr("湿度"));ui->shidu->setText(tr("%1").arg(today.shidu));ui->fengli->setText(tr("%1").arg(today.fengli));ui->fengxiang->setText(tr("%1").arg(today.fengxiang)); ui->label_4->setText(tr("感\n冒\n指\n数"));ui->ganmao->setText(tr("%1").arg(today.ganmao));return;}elsexml.readNext();}elsexml.readNext();}xml.clear();}//搜索框查询天气void MainWindow::on_getButton_clicked(){if(ui->cityEdit->text().isEmpty())return;city = ui->cityEdit->text();if(citykeys[city] == "") {QMessageBox::information(this,tr("抱歉"),tr("暂无此城市的天气情况"),QMessageBox::Ok,QMessageBox::Ok);return;}QString url = URL_1 + citykeys[city];choose = 2;manager->get(QNetworkRequest(QUrl(url)));}//简单换肤void MainWindow::on_updateButton_clicked(){//选择UI的idif(uid == 3)uid = 0;elseuid = uid + 1;//拼凑成UI路径QString UIpath = tr(":/images/UI%1").arg(uid);//qDebug()<<UIpath;//加载UIpixmap.load(UIpath);//产生paintEvent重绘UIupdate();}main.cpp:#include "mainwindow.h"#include <QApplication>int main(int argc, char *argv[]){QApplication a(argc, argv);MainWindow w;w.show();return a.exec();}五、测试数据及分析打开程序:换肤:搜索指定城市天气信息:六、结论:本次我们小组对设计实验所涉及到知识进行讨论,共同研究,查证资料,掌握将要用到的Qt知识并且对我们小组的实验进行主要设计,对小组实验进行分工,本次设计实验结束后我们脑海里已经对QT的知识面得到了延伸!七、参考文献/liang19890820/article/details/52767153 [Qt之JSON生成与解析] /styyzxjq2009/article/details/8041287[Qt XML读取写入操作]/chenlong12580/article/details/7391622 [Qt网络编程之QNetworkAccessManager]。