目錄
一、項目概述
1.1項目背景
1.2項目目標
二、功能需求
2.1 用戶界面功能
2.2 后臺功能
三、技術選擇
3.1 開發框架與工具
3.2 第三方 API
四、UI設計
4.1界面展示
4.2stylesheet樣式
五、代碼實現
1.構造函數
2.網絡請求響應處理函數
3.處理json數據
4.更新UI數據
5.城市搜索按鈕實現
6.鼠標左鍵拖動窗口移動右鍵關閉
7.事件過濾器繪圖
?六、結果測試
一、項目概述
1.1項目背景
????????隨著人們對生活品質要求的提高,天氣預報已成為日常生活的重要組成部分。通過準確的天氣信息,用戶可以更好地規劃出行、穿衣等日常活動。本項目旨在開發一個基于 Qt 框架的天氣預報系統,實現實時天氣數據的獲取、展示以及歷史天氣數據的查詢功能。
1.2項目目標
-
實現天氣數據的 HTTP 請求與解析。
-
展示實時天氣信息(包括溫度、濕度、風速、空氣質量等)。
-
提供未來 7 天天氣預報功能。
-
提供用戶友好的圖形界面。
二、功能需求
2.1 用戶界面功能
-
實時天氣顯示:包括當前溫度、濕度、風速、天氣狀況等。
-
未來天氣預報:
-
24 小時天氣預報(每小時)。
-
7 天天氣預報。
-
-
城市切換:用戶可以選擇不同的城市查看天氣信息。
2.2 后臺功能
-
HTTP 請求接口實現,用于獲取天氣數據。
-
JSON 數據解析模塊,將接收到的 JSON 格式天氣數據轉換為程序可用的數據結構。
三、技術選擇
3.1 開發框架與工具
-
Qt 框架:用于 GUI 界面開發和應用程序邏輯實現。
-
QNetworkAccessManager:用于 HTTP 請求(API 調用)。
-
JSON 解析庫:使用 Qt 提供的?
QJsonDocument
?類解析天氣數據。
3.2 第三方 API
- 使用天氣預報服務提供商的 API(如 OpenWeatherMap、WeatherStack 等),實現天氣數據接口調用。
易客云天氣API免費天氣API接口|天氣預報接口|全球天氣API接口|氣象預警|空氣質量我直接使用了這個網站提供的接口。
四、UI設計
4.1界面展示
將整個界面分為四部分,命名如對應部分所示,在控件比較多的情況下,注意排版技巧,分模塊會更清晰一些,對控件的命名要規律,在后面功能實現的時候編寫代碼會更順。
4.2stylesheet樣式
設置邊框弧度:
border-radius: 4px;
?設置某方向邊框弧度:
border-bottom-left-radius: 0px;
border-bottom-right-radius: 0px;
?設置背景顏色:
background-color: rgba(60, 60, 60, 100);
父控件影響:
?
QLabel {
background-color: rgba(0, 200, 200, 200);
border-radius: 4px;
}
五、代碼實現
1.構造函數
使用Qt框架創建了一個無邊框窗口,固定大小為411x850像素,并設置Arial字體大小為15。創建了一個包含“退出”操作的下拉菜單。點擊該菜單項會觸發關閉當前窗口的操作。使用QNetworkAccessManager
發送HTTP GET請求到指定天氣API接口,以獲取實時天氣數據。定義了處理網絡響應的槽函數readHttpReply
,當網絡請求完成時將調用該函數來處理返回的數據。
2.網絡請求響應處理函數
-
獲取并打印HTTP狀態碼:從
QNetworkReply
對象中提取HTTP狀態碼,并將其輸出到調試控制臺。這有助于在開發和調試過程中快速判斷網絡請求的成功與否。 -
檢查網絡請求是否成功:使用
reply->error()
方法檢查是否存在網絡錯誤,同時驗證HTTP狀態碼是否為200(表示成功的響應)。如果這兩個條件都滿足,則認為請求是成功的。 -
處理成功的網絡響應:讀取所有來自服務器的響應數據,并將其傳遞給新的解析函數
parseWeatherJsonDataNew(data);
。這表明代碼中有專門的函數來解析JSON格式的數據,以便提取有用的信息(如天氣數據)進行后續處理或顯示。 -
處理失敗的網絡響應:如果網絡請求出現錯誤(如連接超時、服務器不可達等),則創建并顯示一個警告對話框。該對話框提示用戶請求失敗,并且按鈕的文字顏色被設置為紅色以增強視覺效果。
3.處理json數據
4.更新UI數據
void Widget::updateUI()
{ui->labelCurrentData->setText(days[0].mDate+" "+days[0].mWeek);//解析城市名稱ui->labelCity->setText(days[0].mCity+"市");//解析當前溫度ui->labelTemp->setText(days[0].mTemp+"°");ui->labelTempRange->setText(days[0].mTempLow+"℃"+"~"+days[0].mTempHigh+"℃");//解析天氣類型ui->labelweatherType->setText(days[0].mWeathType);ui->labelWeatherIcon->setPixmap(mTypeMap[days[0].mWeathType]);//感冒指數ui->labelGanmao->setText(days[0].mTips);//風向ui->labelFXType->setText(days[0].mFx);//風力ui->labelFXType_3->setText(days[0].mFl);//PM2.5ui->labelPM25Data->setText(days[0].mPm25);//濕度ui->labelShiduData->setText(days[0].mHu);//空氣質量ui->labelairData->setText(days[0].mAirq);for(int i=0;i<6;i++){mWeekList[i]->setText(days[i].mWeek);mWeekList[0]->setText("今天");mWeekList[1]->setText("明天");mWeekList[2]->setText("后天");QStringList dayList = days[i].mDate.split("-");mDateList[i]->setText(dayList.at(1)+"-"+dayList.at(2));int index = days[i].mWeathType.indexOf("轉");
// if(index!=-1){
// qDebug()<<days[i].mWeathType.left(index);
// mIconList[i]->setPixmap(mTypeMap[days[i].mWeathType.left(index)]);
// mWeaTypeList[i]->setText(days[i].mWeathType.left(index));
// }mIconList[i]->setPixmap(mTypeMap[days[i].mWeathType]);mWeaTypeList[i]->setText(days[i].mWeathType);QString airQ = days[i].mAirq;mAirqList[i]->setText(airQ);if(airQ=="優"){mAirqList[i]->setStyleSheet("background-color : rgb(150,213,32);border-radius: 7px;");}if(airQ=="良"){mAirqList[i]->setStyleSheet("background-color : rgb(241,224,103);border-radius: 7px;");}if(airQ=="輕度污染"){mAirqList[i]->setStyleSheet("background-color : rgb(255,199,199);border-radius: 7px;");}if(airQ=="中度污染"){mAirqList[i]->setStyleSheet("background-color : rgb(255,17,17);border-radius: 7px;");}if(airQ=="重度污染"){mAirqList[i]->setStyleSheet("background-color : rgb(153,0,0);border-radius: 7px;");}mFxList[i]->setText(days[i].mFx);index = days[i].mFl.indexOf("轉");if(index!=-1){mFlList[i]->setText(days[i].mFl.left(index));}else{mFlList[i]->setText(days[i].mFl);}}update();}