1. MainWindow類設計的成員變量和方法
public:
? ? MainWindow(QWidget* parent = nullptr);
? ? ~MainWindow();? ?protected:
形成文本菜單來用來右鍵關閉窗口
? ? void contextMenuEvent(QContextMenuEvent* event);鼠標被點擊之后此事件被調用
? ? void mousePressEvent(QMouseEvent *ev);
移動窗口
? ? void mouseMoveEvent(QMouseEvent* ev);
? ? //重寫過濾器方法
? ? bool eventFilter(QObject *watched, QEvent *event);private slots://信號槽函數
? ? void onReplied(QNetworkReply* reply);? ? void on_btnSearch_clicked();
public:
? ? void getWeaterInfo(QString cityCode);
? ? //解析json數據
? ? void parseJson(QByteArray& byteArray);
? ? int parseString(QString str);
? ? //更新UI
? ? void UpdateUi();
? ? //檢測空氣質量
? ?int checkedQulity(int api);
? ? //繪制高低溫曲線
? ? void paintHighCurve();
? ?void paintLowCurve();
? ?private:
? ? Ui::MainWindow* ui;? ? QMenu* mExitMenu; ? // 右鍵退出的菜單
? ? QAction* mExitAct; ?// 退出的行為
? ? QPoint m_offset;//鼠標和左上角坐標的偏移距離
? ? QNetworkAccessManager *m_netAccessManager;
? ? Today m_today;
? ? Day m_day[7];? ? //星期和日期
? ? QList<QLabel*> m_weekList;
? ? QList<QLabel*> m_dateList;? ? //天氣和天氣圖標
? ? QList<QLabel*> m_typeList;
? ? QList<QLabel*> m_typeIconList;? ? //天氣污染指數
? ? QList<QLabel*> m_ApiList;? ? //風力和風向
? ? QList<QLabel*> m_FLList;
? ? QList<QLabel*> m_FXList;
把UI控件都放到QList集合里面
//將UI控件放到數組里邊,方便使用循環進行處理m_dateList << ui->lblDate0 << ui->lblDate1 << ui->lblDate2 << ui->lblDate3 << ui->lblDate4 << ui->lblDate5;m_weekList << ui->lblWeek0 << ui->lblWeek1 << ui->lblWeek2 << ui->lblWeek3 << ui->lblWeek4 << ui->lblWeek5;m_ApiList << ui->lblQuality0 << ui->lblQuality1 << ui->lblQuality2 << ui->lblQuality3 << ui->lblQuality4 << ui->lblQuality5;m_typeList << ui->lblType0 << ui->lblType1 << ui->lblType2 << ui->lblType3 << ui->lblType4 << ui->lblType5;m_typeIconList << ui->lblTypeIcon0 << ui->lblTypeIcon1 << ui->lblTypeIcon2 << ui->lblTypeIcon3 << ui->lblTypeIcon4 << ui->lblTypeIcon5;m_FXList << ui->lblFx0 << ui->lblFx1 << ui->lblFx2 << ui->lblFx3 << ui->lblFx4 << ui->lblFx5;m_FLList << ui->lblFl0 << ui->lblFl1 << ui->lblFl2 << ui->lblFl3 << ui->lblFl4 << ui->lblFl5;
? ? QMap <QString,QString> m_typeMap;
2. 右鍵退出
void contextMenuEvent(QContextMenuEvent* event);
mExitMenu->exec(QCursor::pos());event->accept();
QMenu* mExitMenu; ? 右鍵退出的菜單
?// 右鍵菜單:退出程序
? ? mExitMenu = new QMenu(this);//添加一個菜單框
? ? mExitAct = new QAction();
? ? mExitAct->setText(tr("退出"));
? ? mExitAct->setIcon(QIcon(":/res/close.png"));
? ? mExitMenu->addAction(mExitAct);//把這個行為設置到菜單里面去? ? connect(mExitAct, &QAction::triggered, this, [=]() {
? ? ? ? qApp->exit(0);?
? ? });
3.存放天氣信息的類
class Today
{
public:Today(){date = "2022-10-20";city = "廣州";ganmao = "感冒指數";wendu = 0;shidu = "0%";pm25 = 0;quality = "無數據";type = "多云";fl = "2級";fx = "南風";high = 30;low = 18;}QString date;QString city;QString ganmao;int wendu;QString shidu;int pm25;QString quality;QString type;QString fx;QString fl;int high;int low;
};class Day
{
public:Day(){date = "2022-10-20";week = "周五";type = "多云";high = 0;low = 0;fx = "南風";fl = "2級";aqi = 0;}QString date;QString week;QString type;QString ymd;int high;int low;QString fx;QString fl;int aqi;
};
4.get請求數據
void MainWindow::getWeaterInfo(QString cityName) {QString cityCode=weatherTool::getCityCode(cityName);qDebug()<<"cityCode"<<cityCode;QUrl url("http://t.weather.itboy.net/api/weather/city/"+cityCode);m_netAccessManager->get(QNetworkRequest(url));//發送get請求 }
5.重寫void onReplied函數
void onReplied(QNetworkReply* reply);在get請求成功之后此函數被調用
void MainWindow::onReplied(QNetworkReply *reply)
{qDebug()<<"onReplied success";int status_code=reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();qDebug()<<"參數: "<<reply->operation();qDebug()<<"狀態碼: "<<status_code;qDebug()<<"url: "<<reply->url();qDebug()<<"請求頭: "<<reply->rawHeaderList();if(reply->error()!=QNetworkReply::NoError||status_code!=200){qDebug()<<reply->errorString().toLatin1().data();QMessageBox::warning(this,"天氣預報","數據請求失敗",QMessageBox::Ok);}else{QByteArray all=reply->readAll();qDebug()<<"read all : "<<all.data() ;parseJson(all);}reply->deleteLater();}
在此函數里把請求到的數據全部讀出來
6.讀出類之后在調用parseJson(all);來進行解析JSON數據
void MainWindow::parseJson(QByteArray &byteArray)
{QJsonParseError err;QJsonDocument doc=QJsonDocument::fromJson(byteArray,&err);if(err.error!=QJsonParseError::NoError){qDebug()<<"解析Json出錯了";return ;}//Json對象,包括了請求的全部數據QJsonObject rootObj = doc.object();//qDebug() << rootObj;QJsonObject dataObj = rootObj.value("data").toObject();QJsonObject yesterdayObj = dataObj.value("yesterday").toObject();//Json數組,未來幾天的數據QJsonArray forecastArray = dataObj.value("forecast").toArray();//1.解析日期和城市QString str = rootObj.value("time").toString();m_today.date= str.split(" ").at(0);qDebug()<<"今天:"<<m_today.date;m_today.city = rootObj.value("cityInfo").toObject().value("city").toString();//2.解析yesterdaym_day[0].date = yesterdayObj.value("date").toString();//日期m_day[0].aqi = yesterdayObj.value("aqi").toDouble();//空氣質量,toDouble包括整數型m_day[0].type = yesterdayObj.value("type").toString();//天氣類型m_day[0].week = yesterdayObj.value("week").toString();//星期m_day[0].ymd = yesterdayObj.value("ymd").toString();//完整年月日//解析最低溫度和最高溫度/*QString str = yesterdayObj.value("low").toString();//最低溫度str = str.split(" ").at(1);//以空格為分割符,去除前面的文字,取出第二個X℃,str = str.left(str.length() - 1);//去除后面的攝氏度符號mDay[0].low = str.toInt();//傳入最低溫度str.clear();//清除內容str = yesterdayObj.value("high").toString();//最高溫度str = str.split(" ").at(1);//以空格為分割符,去除前面的文字,取出第二個X℃,str = str.left(str.length() - 1);//去除后面的攝氏度符號mDay[0].high = str.toInt();//傳入最高溫度*///簡化版m_day[0].low = parseString(yesterdayObj.value("low").toString());//最低溫度m_day[0].high = parseString(yesterdayObj.value("high").toString());//最高溫度m_day[0].fx = yesterdayObj.value("fx").toString();//風向m_day[0].fl = yesterdayObj.value("fl").toString();//風力//3.解析forecast中的6天數據for (int i = 0; i < 5; ++i) {QJsonObject forecastData = forecastArray[i].toObject();//跳過0,因為0已經賦值給昨天的數據了m_day[i + 1].date = forecastData.value("date").toString();//日期//qDebug()<<"time: "<<m_day[i + 1].date;m_day[i + 1].aqi = forecastData.value("aqi").toDouble();//空氣質量,toDouble包括整數型m_day[i + 1].type = forecastData.value("type").toString();//天氣類型m_day[i + 1].week = forecastData.value("week").toString();//星期m_day[i + 1].low = parseString(forecastData.value("low").toString());//最低溫度m_day[i + 1].high = parseString(forecastData.value("high").toString());//最高溫度m_day[i + 1].fx = forecastData.value("fx").toString();//風向m_day[i + 1].fl = forecastData.value("fl").toString();//風力m_day[i + 1].ymd = forecastData.value("ymd").toString();//完整年月日//ymd分割成MM/dd//QDateTime::fromString(forecastData.value("ymd").toString(), "yyyy-MM-dd").toString("MM/dd");//日期//qDebug() << i << mDay[i + 1].date << mDay[i + 1].aqi << mDay[i + 1].type << mDay[i + 1].week << mDay[i + 1].low << mDay[i + 1].high << mDay[i + 1].fx << mDay[i + 1].fl;//qDebug() << i << mDay[i].date;//qDebug() << mDay[i + 1].ymd;}//4.解析今天的數據m_today.shidu = dataObj.value("shidu").toString();m_today.quality = dataObj.value("quality").toString();m_today.ganmao = dataObj.value("ganmao").toString();m_today.pm25 = dataObj.value("pm25").toDouble();m_today.wendu = dataObj.value("wendu").toString().toInt();//qDebug() << dataObj;//qDebug() << mToday.shidu << mToday.quality << mToday.ganmao << mToday.pm25 << mToday.wendu;//注意:forecast中的第2個元素也是今天的數據m_today.type = m_day[1].type;qDebug()<<"今天的天氣是: "<<m_today.type;m_today.low = m_day[1].low;m_today.high = m_day[1].high;m_today.fx = m_day[1].fx;m_today.fl = m_day[1].fl;//qDebug() << mToday.type << mToday.low << mToday.high << mToday.fx << mToday.fl;UpdateUi();//更新曲線在搜索城市完成后手動更新曲線ui->lblHighCurve->update();ui->lblLowCurve->update();
}
解析完JSON數據之后在更新ui(UpdateUi();)
7.更新UI
void MainWindow::UpdateUi()
{ui->lblDate->setText(QDateTime::fromString(m_today.date,"yyyyMMdd").toString("yyyy/MM/dd")+" "+m_day[1].week);ui->lblCity->setText(m_today.city);//更新今天數據ui->lblTypeIcon->setPixmap(m_typeMap[m_today.type]);//更新圖片ui->lblTemp->setText(QString ::number(m_today.wendu));ui->lblType->setText(m_today.type);ui->lblLowHigh->setText(QString ::number(m_today.low)+"℃ ~ "+QString::number(m_today.high)+"℃");ui->lblGanMao->setText("感冒指數: "+m_today.ganmao);ui->lblWindFl->setText(m_today.fl);ui->lblWindFx->setText(m_today.fx);ui->lblPM25->setText(QString::number(m_today.pm25));ui->lblShiDu->setText(m_today.shidu);ui->lblQuality->setText(m_today.quality);//更新六天for(int i=0;i<6;i++){//更新日期和時間m_weekList[i]->setText("周"+m_day[i].week.right(1));//從右邊取第一個ui->lblWeek0->setText("昨天");ui->lblWeek1->setText("今天");ui->lblWeek2->setText("明天");// //把日期提取出來變成 10/10格式QStringList slist=m_day[i].ymd.split("-");qDebug()<<slist;m_dateList[i]->setText(slist.at(1)+"/"+slist.at(2));//更新天氣類型m_typeList[i]->setText(m_day[i].type);m_typeIconList[i]->setPixmap(m_typeMap[m_day[i].type]);//更新圖片
//空氣質量switch (checkedQulity(m_day[i].aqi)) {case 1:m_ApiList[i]->setText("優");m_ApiList[i]->setStyleSheet("background-color: rgb(121,184,0);");break;case 2:m_ApiList[i]->setText("良");m_ApiList[i]->setStyleSheet("background-color: rgb(255,187,23);");break;case 3:m_ApiList[i]->setText("輕度");m_ApiList[i]->setStyleSheet("background-color: rgb(255,87,97);");break;case 4:m_ApiList[i]->setText("中度");m_ApiList[i]->setStyleSheet("background-color: rgb(235,17,27);");break;case 5:m_ApiList[i]->setText("重度");m_ApiList[i]->setStyleSheet("background-color: rgb(170,0,0);");break;case 6:m_ApiList[i]->setText("嚴重");m_ApiList[i]->setStyleSheet("background-color: rgb(110,0,0);");break;}//風力風向m_FXList[i]->setText(m_day[i].fx);m_FLList[i]->setText(m_day[i].fl);}}//檢查空氣質量
int MainWindow::checkedQulity(int aqi)
{if (aqi >= 0 && aqi <= 50) {return 1;}else if(aqi > 50 && aqi <= 100){return 2;}else if(aqi > 100 && aqi <= 150){return 3;}else if(aqi > 150 && aqi <= 200){return 4;}else if(aqi > 200 && aqi <= 250){return 5;}else{return 6;}return -1;
}
8.實現搜索框搜索城市
獲取LeCity搜索框輸入的數據
void MainWindow::on_btnSearch_clicked()
{QString cityName=ui->leCity->text();getWeaterInfo(cityName);
}
天氣工具類
//天氣工具類
class weatherTool{
private://內聯靜態變量 在占用調用處的內存inline static QMap<QString,QString> m_cityMap={};static void initCityMap(){QFile fd("E:\\code\\citycode.json");fd.open(QIODevice::ReadOnly|QIODevice::Text);QByteArray allJson=fd.readAll();fd.close();QJsonParseError err;//讀出的數據轉換為json的QJsonDocument doc= QJsonDocument::fromJson(allJson,&err);if(err.error!=QJsonParseError::NoError||!doc.isArray()){//不是數組就錯誤qDebug()<<"json數據轉換失敗...";return;} //轉換成json數組QJsonArray rootArray=doc.array();for(int i=0;i<rootArray.size();i++){QString cityName = rootArray[i].toObject().value("city_name").toString();QString cityCode = rootArray[i].toObject().value("city_code").toString();//判斷編號是否存在if(cityCode.size()>0){m_cityMap.insert(cityName,cityCode);}}}public :QString static getCityCode(QString cityName){qDebug()<<"cityName"<<cityName;if(m_cityMap.isEmpty()){qDebug()<< m_cityMap.isEmpty();initCityMap();}if(cityName==""){QMessageBox::warning(nullptr,"錯誤(null)","輸入的城市不能為空...",QMessageBox::Ok);return "";}//在map尋找傳入的城市名稱,返回值可以遍歷//返回的是map中的多個元素QMap<QString, QString>::iterator it = m_cityMap.find(cityName);//到結尾了,未找到,加上市,再搜一遍if (it == m_cityMap.end()) {it = m_cityMap.find(cityName + "市");}//找到了if (it != m_cityMap.end()) {qDebug()<<" if (it != m_cityMap.end())";return it.value();}QMessageBox::warning(nullptr,"城市名字錯誤","輸入的城市名字錯誤...",QMessageBox::Ok);//否則return "";}};
讀取這個文件里面的數據QFile fd("E:\\code\\citycode.json");把city_name和city_code取出來放到QMap集合里面去,之后在和輸入的CityName進行查找獲得city_code.
?
?