├── .gitignore ├── README.md ├── demonstrate └── demonstrate.gif ├── image ├── autumn.png ├── cloudy_moon.png ├── cloudy_sun.png ├── fine_moon.png ├── fine_sun.png ├── rain_moon.png ├── rain_sun.png ├── snow_moon.png ├── snow_sun.png ├── spring.png ├── summer.png ├── thundershower.png └── winter.png ├── qml.qrc ├── src ├── main.cpp ├── main.qml ├── myjsonparse.cpp ├── myjsonparse.h ├── mymodel.cpp ├── mymodel.h ├── weatherdata.cpp └── weatherdata.h └── weather.pro /.gitignore: -------------------------------------------------------------------------------- 1 | debug/ 2 | release/ 3 | *.user 4 | *.Debug 5 | *.Release 6 | Makefile 7 | *.stash 8 | *.rc 9 | *.exe 10 | *.qmlc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/README.md -------------------------------------------------------------------------------- /demonstrate/demonstrate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/demonstrate/demonstrate.gif -------------------------------------------------------------------------------- /image/autumn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/autumn.png -------------------------------------------------------------------------------- /image/cloudy_moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/cloudy_moon.png -------------------------------------------------------------------------------- /image/cloudy_sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/cloudy_sun.png -------------------------------------------------------------------------------- /image/fine_moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/fine_moon.png -------------------------------------------------------------------------------- /image/fine_sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/fine_sun.png -------------------------------------------------------------------------------- /image/rain_moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/rain_moon.png -------------------------------------------------------------------------------- /image/rain_sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/rain_sun.png -------------------------------------------------------------------------------- /image/snow_moon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/snow_moon.png -------------------------------------------------------------------------------- /image/snow_sun.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/snow_sun.png -------------------------------------------------------------------------------- /image/spring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/spring.png -------------------------------------------------------------------------------- /image/summer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/summer.png -------------------------------------------------------------------------------- /image/thundershower.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/thundershower.png -------------------------------------------------------------------------------- /image/winter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mengps/Weather/eff48ab07102707702101314339d1cb391f750c5/image/winter.png -------------------------------------------------------------------------------- /qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | image/spring.png 4 | image/summer.png 5 | image/winter.png 6 | image/fine_moon.png 7 | image/fine_sun.png 8 | image/rain_moon.png 9 | image/rain_sun.png 10 | image/snow_moon.png 11 | image/snow_sun.png 12 | image/thundershower.png 13 | image/cloudy_moon.png 14 | image/cloudy_sun.png 15 | image/autumn.png 16 | src/main.qml 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "mymodel.h" 2 | #include "weatherdata.h" 3 | #include 4 | #include 5 | #include 6 | 7 | int main(int argc, char *argv[]) 8 | { 9 | QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 10 | QApplication app(argc, argv); 11 | 12 | qmlRegisterType("an.weather", 1, 0, "IndexData"); 13 | qmlRegisterType("an.weather", 1, 0, "WeatherData"); 14 | qmlRegisterType("an.model", 1, 0, "MyModel"); 15 | 16 | QQmlApplicationEngine engine; 17 | MyModel *myModel = new MyModel(); 18 | engine.rootContext()->setContextProperty("myModel", myModel); 19 | engine.load(QUrl(QLatin1String("qrc:/src/main.qml"))); 20 | if (engine.rootObjects().isEmpty()) 21 | return -1; 22 | 23 | return app.exec(); 24 | } 25 | -------------------------------------------------------------------------------- /src/main.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.7 2 | import QtQuick.Controls 2.2 3 | import QtQuick.Window 2.3 4 | import QtCharts 2.2 5 | import an.weather 1.0 6 | import an.model 1.0 7 | 8 | ApplicationWindow 9 | { 10 | id: root 11 | 12 | width: mobile ? Screen.desktopAvailableWidth : 400 13 | height: mobile ? Screen.desktopAvailableHeight : 600 14 | color: "#CDEDEC" 15 | visible: true 16 | 17 | property bool mobile: Qt.platform.os == "android"; 18 | 19 | Connections 20 | { 21 | target: myModel 22 | onReadyChanged: 23 | { 24 | if (myModel.ready) 25 | { 26 | refreshAnimation.restart(); 27 | maxSeries.clear(); 28 | minSeries.clear(); 29 | for (var i = 0; i < 4; i++) 30 | { 31 | maxSeries.append(i + 1, myModel.weatherData[i].maxTemperature); 32 | minSeries.append(i + 1, myModel.weatherData[i].minTemperature); 33 | } 34 | } 35 | } 36 | } 37 | 38 | NumberAnimation 39 | { 40 | id: refreshAnimation 41 | target: page 42 | property: "y" 43 | duration: 200 44 | from: page.pullHeight 45 | to: 0 46 | easing.type: Easing.Linear 47 | } 48 | 49 | Image 50 | { 51 | id: season //季节背景 52 | anchors.fill: parent 53 | fillMode: Image.PreserveAspectFit 54 | mipmap: true 55 | antialiasing: true 56 | opacity: 0.4 57 | source: getSeason() 58 | 59 | function getSeason() 60 | { 61 | var time = new Date(); 62 | var season = time.getMonth() / 3; 63 | 64 | if (season <= 1) 65 | return "qrc:image/spring.png"; 66 | else if (season > 1 && season <= 2) 67 | return "qrc:image/summer.png"; 68 | else if (season > 2 && season <= 3) 69 | return "qrc:image/autumn.png"; 70 | else return "qrc:image/winter.png"; 71 | } 72 | } 73 | 74 | Component 75 | { 76 | id: delegate 77 | 78 | Item 79 | { 80 | width: 70 81 | height: 220 82 | 83 | Text 84 | { 85 | id: dateText 86 | width: 70 87 | height: 20 88 | font.family: "方正" 89 | font.pointSize: 10 90 | horizontalAlignment: Text.AlignHCenter 91 | verticalAlignment: Text.AlignVCenter 92 | text: index != 0 ? date : "今日" 93 | } 94 | 95 | Text 96 | { 97 | id: weatherText 98 | width: 70 99 | height: 20 100 | font.family: "方正" 101 | font.pointSize: 10 102 | anchors.top: dateText.bottom 103 | anchors.topMargin: 5 104 | horizontalAlignment: Text.AlignHCenter 105 | verticalAlignment: Text.AlignVCenter 106 | text: myModel.ready ? weather : "未知" 107 | } 108 | 109 | Image 110 | { 111 | id: day 112 | anchors.top: weatherText.bottom 113 | anchors.topMargin: 2 114 | width: 70 115 | height: 50 116 | mipmap: true 117 | fillMode: Image.PreserveAspectFit 118 | source: myModel.ready ? dayPicture : "" 119 | } 120 | 121 | Text 122 | { 123 | id: temperatureText 124 | width: 70 125 | height: 20 126 | font.family: "方正" 127 | font.pointSize: 10 128 | anchors.top: day.bottom 129 | anchors.topMargin: 5 130 | horizontalAlignment: Text.AlignHCenter 131 | verticalAlignment: Text.AlignVCenter 132 | text: myModel.ready ? myModel.weatherData[index].minTemperature + " ~ " + 133 | myModel.weatherData[index].maxTemperature + "℃" : "未知" 134 | } 135 | 136 | Image 137 | { 138 | id: night 139 | anchors.top: temperatureText.bottom 140 | anchors.topMargin: 5 141 | width: 70 142 | height: 50 143 | mipmap: true 144 | fillMode: Image.PreserveAspectFit 145 | source: myModel.ready ? nightPicture : "" 146 | } 147 | 148 | Text 149 | { 150 | id: windText 151 | width: 70 152 | height: 20 153 | font.family: "方正" 154 | font.pointSize: 10 155 | anchors.top: night.bottom 156 | anchors.topMargin: 5 157 | horizontalAlignment: Text.AlignHCenter 158 | verticalAlignment: Text.AlignVCenter 159 | text: myModel.ready ? wind : "未知" 160 | } 161 | } 162 | } 163 | 164 | Flickable 165 | { 166 | id: page 167 | width: parent.width 168 | height: parent.height 169 | contentWidth: content.width 170 | contentHeight: content.height 171 | 172 | property int pullHeight: 64 173 | 174 | states: [ 175 | State { 176 | id: downRefreshState 177 | name: "downRefresh" 178 | when: page.contentY < -page.pullHeight 179 | StateChangeScript 180 | { 181 | script: 182 | { 183 | print("下拉刷新") 184 | page.y = page.pullHeight 185 | myModel.downRefresh(); 186 | } 187 | } 188 | } 189 | ] 190 | 191 | Item 192 | { 193 | id: content 194 | width: root.width 195 | height: tipsRect.y + tipsRect.height + 50 196 | 197 | Text 198 | { 199 | id: city 200 | anchors.horizontalCenter: parent.horizontalCenter 201 | anchors.top: parent.top 202 | anchors.topMargin: 5 203 | font.pointSize: 18 204 | font.family: "方正" 205 | text: "城市:" + (myModel.ready ? myModel.city : "载入中...") 206 | } 207 | 208 | Text 209 | { 210 | id: updateMsg 211 | anchors.horizontalCenter: city.horizontalCenter 212 | anchors.top: city.bottom 213 | anchors.topMargin: 5 214 | font.pointSize: 8 215 | font.family: "方正" 216 | color: "gray" 217 | text: myModel.ready ? "天气数据已经更新" : "天气数据更新中...." 218 | } 219 | 220 | Text 221 | { 222 | id: temperature 223 | anchors.horizontalCenter: updateMsg.horizontalCenter 224 | anchors.top: updateMsg.bottom 225 | anchors.topMargin: 70 226 | font.pointSize: 14 227 | font.family: "方正" 228 | text: "今日温度:" + (myModel.ready ? myModel.weatherData[0].minTemperature 229 | + " ~ " + myModel.weatherData[0].maxTemperature + "℃": "载入中...") 230 | } 231 | 232 | Text 233 | { 234 | id: pm25 235 | anchors.horizontalCenter: temperature.horizontalCenter 236 | anchors.top: temperature.bottom 237 | anchors.topMargin: 10 238 | font.pointSize: 14 239 | font.family: "方正" 240 | text: "空气污染(PM2.5):" + (myModel.ready ? myModel.pm25 + calcPollutionLevel(myModel.pm25) : "载入中...") 241 | function calcPollutionLevel(arg) 242 | { 243 | var intArg = parseInt(arg); 244 | if (intArg >= 0 && intArg < 35) 245 | return "(优秀)"; 246 | else if (intArg >= 35 && intArg < 75) 247 | return "(良好)"; 248 | else if (intArg >= 75 && intArg < 115) 249 | return "(轻度污染)"; 250 | else if (intArg >= 115 && intArg < 150) 251 | return "(中度污染)"; 252 | else if (intArg >= 150 && intArg < 250) 253 | return "(重度污染)"; 254 | else return "(严重污染)"; 255 | } 256 | } 257 | 258 | Text 259 | { 260 | id: time 261 | anchors.horizontalCenter: pm25.horizontalCenter 262 | anchors.top: pm25.bottom 263 | anchors.topMargin: 10 264 | font.pointSize: 14 265 | font.family: "方正" 266 | color: "red" 267 | text: myModel.ready ? myModel.weatherData[0].date : "载入中..." 268 | } 269 | 270 | Row 271 | { 272 | id: day_night 273 | anchors.horizontalCenter: parent.horizontalCenter 274 | anchors.top: time.bottom 275 | anchors.topMargin: 10 276 | spacing: 15 277 | 278 | Image 279 | { 280 | width: 100 281 | height: 50 282 | mipmap: true 283 | fillMode: Image.PreserveAspectFit 284 | source: myModel.ready ? myModel.weatherData[0].dayPicture : "" 285 | } 286 | 287 | Image 288 | { 289 | width: 100 290 | height: 50 291 | mipmap: true 292 | fillMode: Image.PreserveAspectFit 293 | source: myModel.ready ? myModel.weatherData[0].nightPicture : "" 294 | } 295 | } 296 | 297 | Row 298 | { 299 | id: day_night_text 300 | anchors.top: day_night.bottom 301 | anchors.topMargin: 2 302 | anchors.horizontalCenter: day_night.horizontalCenter 303 | 304 | Text 305 | { 306 | width: 120 307 | height: 20 308 | font.pointSize: 11 309 | font.family: "方正" 310 | horizontalAlignment: Text.AlignHCenter 311 | verticalAlignment: Text.AlignVCenter 312 | text: qsTr("白天") 313 | } 314 | 315 | Text 316 | { 317 | width: 120 318 | height: 20 319 | font.pointSize: 11 320 | font.family: "方正" 321 | horizontalAlignment: Text.AlignHCenter 322 | verticalAlignment: Text.AlignVCenter 323 | text: qsTr("夜晚") 324 | } 325 | } 326 | 327 | ListView 328 | { 329 | id: futureWeather 330 | width: contentWidth 331 | orientation: ListView.Horizontal 332 | anchors.top: day_night_text.bottom 333 | anchors.topMargin: 50 334 | anchors.horizontalCenter: day_night_text.horizontalCenter 335 | spacing: 20 336 | model: myModel.weatherData 337 | delegate: delegate 338 | } 339 | 340 | ChartView 341 | { 342 | id: futureChart 343 | width: parent.width 344 | height: 200 345 | legend.font.family: "方正" 346 | legend.font.pointSize: 10 347 | y: futureWeather.y + 190 348 | anchors.horizontalCenter: futureWeather.horizontalCenter 349 | antialiasing: true 350 | backgroundColor: "transparent" 351 | plotAreaColor: "transparent" 352 | Component.onCompleted: 353 | { 354 | futureChart.axisX().visible = false; 355 | futureChart.axisY().visible = false; 356 | } 357 | 358 | ValueAxis 359 | { 360 | id: axisX 361 | min: 0.5 362 | max: 4.5 363 | } 364 | 365 | ValueAxis 366 | { 367 | id: axisY 368 | min: -5 369 | max: 40 370 | } 371 | 372 | LineSeries 373 | { 374 | id: maxSeries 375 | name: "最高温" 376 | pointLabelsFont.family: "方正" 377 | pointLabelsFont.pointSize: 10 378 | pointLabelsVisible: true 379 | pointLabelsFormat: "@yPoint °" //更改label的格式 380 | color: "red" 381 | width: 2 382 | axisX: axisX 383 | axisY: axisY 384 | } 385 | 386 | LineSeries 387 | { 388 | id: minSeries 389 | name: "最低温" 390 | pointLabelsFont.family: "方正" 391 | pointLabelsFont.pointSize: 10 392 | pointLabelsVisible: true 393 | pointLabelsFormat: "@yPoint °" 394 | color: "#8080FF" 395 | width: 2 396 | axisX: axisX 397 | axisY: axisY 398 | } 399 | } 400 | 401 | Rectangle 402 | { 403 | id: tipsRect 404 | width: parent.width - 40 405 | height: 280 406 | radius: 5 407 | clip: true 408 | anchors.top: futureChart.bottom 409 | anchors.topMargin: 10 410 | anchors.horizontalCenter: futureWeather.horizontalCenter 411 | color: "#335C8D89" 412 | 413 | Text 414 | { 415 | id: tipsText 416 | text: "小提示:" 417 | anchors.left: tipsRect.left 418 | anchors.leftMargin: 15 419 | anchors.top: tipsRect.top 420 | anchors.topMargin: 15 421 | font.pointSize: 13 422 | font.bold: true 423 | font.family: "方正" 424 | horizontalAlignment: Text.AlignHCenter 425 | verticalAlignment: Text.AlignVCenter 426 | color: "#FC993C" 427 | } 428 | 429 | Flickable //之所以使用一个Flickable,是因为下面的ListView的滑动失效了,具体原因不明 430 | { 431 | anchors.left: tipsRect.left 432 | anchors.leftMargin: 10 433 | anchors.right: tipsRect.right 434 | anchors.rightMargin: 10 435 | anchors.top: tipsText.bottom 436 | anchors.topMargin: 10 437 | width: parent.width 438 | height: parent.height 439 | contentWidth: tipsView.contentWidth 440 | contentHeight: tipsView.contentHeight 441 | 442 | ListView 443 | { 444 | id: tipsView 445 | height: parent.width 446 | width: parent.width 447 | orientation: ListView.Horizontal 448 | model: myModel.indexData 449 | spacing: 20 450 | delegate: Component 451 | { 452 | Column 453 | { 454 | spacing: 20 455 | 456 | Text 457 | { 458 | id: title 459 | width: 80 460 | text: modelData.title 461 | horizontalAlignment: Text.AlignHCenter 462 | verticalAlignment: Text.AlignVCenter 463 | font.pointSize: 11 464 | font.family: "方正" 465 | } 466 | 467 | Text 468 | { 469 | id: tipt 470 | width: 80 471 | text: modelData.tipt 472 | horizontalAlignment: Text.AlignHCenter 473 | verticalAlignment: Text.AlignVCenter 474 | font.pointSize: 11 475 | font.family: "方正" 476 | } 477 | 478 | Text 479 | { 480 | id: state 481 | width: 80 482 | text: modelData.state 483 | horizontalAlignment: Text.AlignHCenter 484 | verticalAlignment: Text.AlignVCenter 485 | font.pointSize: 11 486 | font.family: "方正" 487 | } 488 | 489 | Text 490 | { 491 | id: descript 492 | width: 80 493 | text: modelData.descript 494 | wrapMode: Text.Wrap 495 | horizontalAlignment: Text.AlignHCenter 496 | verticalAlignment: Text.AlignVCenter 497 | font.pointSize: 11 498 | font.family: "方正" 499 | } 500 | } 501 | } 502 | } 503 | } 504 | } 505 | } 506 | } 507 | } 508 | -------------------------------------------------------------------------------- /src/myjsonparse.cpp: -------------------------------------------------------------------------------- 1 | #include "myjsonparse.h" 2 | #include "weatherdata.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | MyJsonParse::MyJsonParse() 9 | : m_success(false) 10 | { 11 | 12 | } 13 | 14 | MyJsonParse::MyJsonParse(const QJsonDocument &doc) 15 | : m_success(false), 16 | m_jsonDoc(doc) 17 | { 18 | 19 | } 20 | 21 | MyJsonParse::~MyJsonParse() 22 | { 23 | 24 | } 25 | 26 | void MyJsonParse::setJsonDocument(const QJsonDocument &doc) 27 | { 28 | if (!doc.isNull()) 29 | m_jsonDoc = doc; 30 | if (m_jsonDoc.isObject()) 31 | { 32 | QJsonObject object = m_jsonDoc.object(); 33 | //用于判断api返回的数据是否可用 34 | m_success = object.value("status").toString() == "success"; 35 | } 36 | } 37 | 38 | QJsonDocument MyJsonParse::jsonDocument() const 39 | { 40 | return m_jsonDoc; 41 | } 42 | 43 | QString MyJsonParse::getCurrentCity() const 44 | { 45 | if (m_success) 46 | { 47 | QJsonObject object = m_jsonDoc.object(); 48 | QJsonArray result = object.value("results").toArray(); 49 | object = result[0].toObject(); 50 | return object.value("currentCity").toString(); 51 | } 52 | return "获取城市失败"; 53 | } 54 | 55 | QString MyJsonParse::getPm25() const 56 | { 57 | if (m_success) 58 | { 59 | QJsonObject object = m_jsonDoc.object(); 60 | QJsonArray result = object.value("results").toArray(); 61 | object = result[0].toObject(); 62 | return object.value("pm25").toString(); 63 | } 64 | return "获取PM25失败"; 65 | } 66 | 67 | QList MyJsonParse::getIndexList() const 68 | { 69 | QList indexs; 70 | if (m_success) 71 | { 72 | QJsonObject object = m_jsonDoc.object(); 73 | QJsonArray array = object.value("results").toArray(); 74 | object = array[0].toObject(); 75 | array = object.value("index").toArray(); 76 | for (auto it : array) 77 | { 78 | object = it.toObject(); 79 | IndexData *indexData = new IndexData; 80 | indexData->setDescript(object.value("des").toString()); 81 | indexData->setTipt(object.value("tipt").toString()); 82 | indexData->setTitle(object.value("title").toString()); 83 | indexData->setState(object.value("zs").toString()); 84 | indexs.push_back(indexData); 85 | } 86 | } 87 | return indexs; 88 | } 89 | 90 | QList MyJsonParse::getWeatherList() const 91 | { 92 | QList weathers; 93 | if (m_success) 94 | { 95 | QJsonObject object = m_jsonDoc.object(); 96 | QJsonArray array = object.value("results").toArray(); 97 | object = array[0].toObject(); 98 | array = object.value("weather_data").toArray(); 99 | for (auto it : array) 100 | { 101 | object = it.toObject(); 102 | WeatherData *weatherData = new WeatherData; 103 | weatherData->setDate(object.value("date").toString()); 104 | //温度的格式为 max ~ min℃; 105 | QString temperature = object.value("temperature").toString(); 106 | QStringList temperatures = temperature.left(temperature.length() - 1).split(" ~ "); 107 | weatherData->setMaxTemperature(temperatures.at(0).toInt()); 108 | weatherData->setMinTemperature(temperatures.at(1).toInt()); 109 | QString weather = object.value("weather").toString(); 110 | weatherData->setWeather(weather); 111 | QString imagestr; 112 | if (weather.left(1) == "晴") //晴或晴转xx 113 | imagestr = "fine"; 114 | else if ((weather.left(2) == "多云" ) || weather.left(1) == "阴") //多云或多云转xx 阴或阴转xx 115 | imagestr = "cloudy"; 116 | else if (weather.contains("雨")) 117 | imagestr = "rain"; 118 | else if (weather.contains("雪")) 119 | imagestr = "snow"; 120 | else imagestr = "fine"; 121 | weatherData->setDayPicture("qrc:/image/" + imagestr + "_sun.png"); 122 | weatherData->setNightPicture("qrc:/image/" + imagestr + "_moon.png"); 123 | weatherData->setWind(object.value("wind").toString()); 124 | weathers.push_back(weatherData); 125 | } 126 | } 127 | 128 | return weathers; 129 | } 130 | -------------------------------------------------------------------------------- /src/myjsonparse.h: -------------------------------------------------------------------------------- 1 | #ifndef MYJSONPARSE_H 2 | #define MYJSONPARSE_H 3 | #include 4 | #include 5 | 6 | class IndexData; 7 | class WeatherData; 8 | class MyJsonParse 9 | { 10 | public : 11 | MyJsonParse(); 12 | MyJsonParse(const QJsonDocument &doc); 13 | ~MyJsonParse(); 14 | 15 | void setJsonDocument(const QJsonDocument &doc); 16 | QJsonDocument jsonDocument() const; 17 | 18 | public: 19 | QString getCurrentCity() const; 20 | QString getPm25() const; 21 | QList getIndexList() const; 22 | QList getWeatherList() const; 23 | 24 | private: 25 | bool m_success; 26 | QJsonDocument m_jsonDoc; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/mymodel.cpp: -------------------------------------------------------------------------------- 1 | #include "mymodel.h" 2 | #include "weatherdata.h" 3 | #include 4 | 5 | class MyModelPrivate 6 | { 7 | public: 8 | MyModelPrivate() { } 9 | ~MyModelPrivate() { cleanup(); } 10 | 11 | void cleanup() 12 | { 13 | if (!m_index.isEmpty()) 14 | { 15 | for (auto it : m_index) 16 | delete it; 17 | m_index.clear(); 18 | } 19 | 20 | if (!m_data.isEmpty()) 21 | { 22 | for (auto it : m_data) 23 | delete it; 24 | m_data.clear(); 25 | } 26 | } 27 | 28 | public: 29 | QString m_city; 30 | QString m_pm25; 31 | QList m_index; 32 | QList m_data; 33 | }; 34 | 35 | MyModel::MyModel(QObject *parent) 36 | : QObject(parent), 37 | m_netManager(new QNetworkAccessManager(this)), 38 | m_ready(false), 39 | m_dptr(new MyModelPrivate), 40 | m_api("http://api.map.baidu.com/telematics/v3/weather" 41 | "?location=武汉&output=json&ak=YGtqUyHOKe5xtaDzi2pmMZVEMdDNlG8F") 42 | { 43 | readSettings(); 44 | m_geoPosSrc = QGeoPositionInfoSource::createDefaultSource(this); 45 | connect(m_geoPosSrc, &QGeoPositionInfoSource::positionUpdated, this, &MyModel::updatePosition); 46 | connect(m_netManager, &QNetworkAccessManager::finished, this, &MyModel::updateWeather); 47 | m_timerID = startTimer(1000 * 60 * 5); //五分钟更新一次天气 48 | m_geoPosSrc->startUpdates(); 49 | //如果位置获取失败,则使用默认位置 50 | if (m_geoPosSrc->error() != QGeoPositionInfoSource::NoError) 51 | m_netManager->get(QNetworkRequest(QUrl(m_api))); 52 | } 53 | 54 | MyModel::~MyModel() 55 | { 56 | delete m_dptr; 57 | if (m_timerID != 0) 58 | killTimer(m_timerID); 59 | } 60 | 61 | void MyModel::readSettings() 62 | { 63 | QSettings setting("Settings//local.ini", QSettings::IniFormat); 64 | QString api = setting.value("api").toString(); 65 | if (!api.isEmpty()) 66 | m_api = api; 67 | } 68 | 69 | void MyModel::writeSettings() 70 | { 71 | QSettings setting("Settings//local.ini", QSettings::IniFormat); 72 | setting.setValue("api", m_api); 73 | } 74 | 75 | void MyModel::downRefresh() 76 | { 77 | setReady(false); 78 | m_netManager->get(QNetworkRequest(QUrl(m_api))); 79 | } 80 | 81 | void MyModel::updatePosition(QGeoPositionInfo gpsPos) 82 | { 83 | if (gpsPos.isValid()) 84 | { 85 | //获取经纬度 86 | QString pos = QString("%1,%2").arg(gpsPos.coordinate().longitude()).arg(gpsPos.coordinate().latitude()); 87 | m_api = QString("http://api.map.baidu.com/telematics/v3/weather" 88 | "?location=%1&output=json&ak=YGtqUyHOKe5xtaDzi2pmMZVEMdDNlG8F").arg(pos); 89 | m_netManager->get(QNetworkRequest(QUrl(m_api))); 90 | writeSettings(); 91 | } 92 | } 93 | 94 | void MyModel::updateWeather(QNetworkReply *reply) 95 | { 96 | QString str = reply->readAll(); 97 | QJsonParseError error; 98 | QJsonDocument doc = QJsonDocument::fromJson(str.toUtf8(), &error); 99 | if (!doc.isNull() && (error.error == QJsonParseError::NoError)) 100 | { 101 | m_parse.setJsonDocument(doc); 102 | setPm25(m_parse.getPm25()); 103 | setCity(m_parse.getCurrentCity()); 104 | m_dptr->m_index = m_parse.getIndexList(); 105 | m_dptr->m_data = m_parse.getWeatherList(); 106 | setReady(true); 107 | emit indexDataChanged(); 108 | emit weatherDataChanged(); 109 | } 110 | } 111 | 112 | void MyModel::timerEvent(QTimerEvent *event) 113 | { 114 | Q_UNUSED(event) 115 | downRefresh(); 116 | } 117 | 118 | QQmlListProperty MyModel::indexData() 119 | { 120 | return QQmlListProperty(this, m_dptr->m_index); 121 | } 122 | 123 | QQmlListProperty MyModel::weatherData() 124 | { 125 | return QQmlListProperty(this, m_dptr->m_data); 126 | } 127 | 128 | QString MyModel::city() const 129 | { 130 | return m_dptr->m_city; 131 | } 132 | 133 | bool MyModel::ready() const 134 | { 135 | return m_ready; 136 | } 137 | 138 | void MyModel::setReady(bool arg) 139 | { 140 | if (arg != m_ready) 141 | { 142 | m_ready = arg; 143 | emit readyChanged(); 144 | } 145 | } 146 | 147 | QString MyModel::pm25() const 148 | { 149 | return m_dptr->m_pm25; 150 | } 151 | 152 | void MyModel::setCity(const QString &arg) 153 | { 154 | if (arg != m_dptr->m_city) 155 | { 156 | m_dptr->m_city = arg; 157 | emit cityChanged(); 158 | } 159 | } 160 | 161 | void MyModel::setPm25(const QString &arg) 162 | { 163 | if (arg != m_dptr->m_pm25) 164 | { 165 | m_dptr->m_pm25 = arg; 166 | emit pm25Changed(); 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/mymodel.h: -------------------------------------------------------------------------------- 1 | #ifndef MYMODEL_H 2 | #define MYMODEL_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "myjsonparse.h" 10 | 11 | class MyModelPrivate; 12 | class MyModel : public QObject 13 | { 14 | Q_OBJECT 15 | 16 | Q_PROPERTY(QQmlListProperty indexData READ indexData NOTIFY indexDataChanged) 17 | Q_PROPERTY(QQmlListProperty weatherData READ weatherData NOTIFY weatherDataChanged) 18 | Q_PROPERTY(QString city READ city WRITE setCity NOTIFY cityChanged) 19 | Q_PROPERTY(QString pm25 READ pm25 WRITE setPm25 NOTIFY pm25Changed) 20 | Q_PROPERTY(bool ready READ ready WRITE setReady NOTIFY readyChanged) 21 | 22 | public: 23 | MyModel(QObject *parent = nullptr); 24 | ~MyModel(); 25 | 26 | QQmlListProperty indexData(); 27 | QQmlListProperty weatherData(); 28 | 29 | QString city() const; 30 | QString pm25() const; 31 | bool ready() const; 32 | void readSettings(); 33 | void writeSettings(); 34 | 35 | public slots: 36 | void downRefresh(); //下拉刷新 37 | void setReady(bool arg); 38 | void setCity(const QString &arg); 39 | void setPm25(const QString &arg); 40 | void updatePosition(QGeoPositionInfo gpsPos); 41 | void updateWeather(QNetworkReply *reply); 42 | 43 | protected: 44 | void timerEvent(QTimerEvent *event); 45 | 46 | signals: 47 | void indexDataChanged(); 48 | void weatherDataChanged(); 49 | void readyChanged(); 50 | void cityChanged(); 51 | void pm25Changed(); 52 | 53 | private: 54 | MyModelPrivate *m_dptr; 55 | QGeoPositionInfoSource *m_geoPosSrc; 56 | QNetworkAccessManager *m_netManager; 57 | MyJsonParse m_parse; 58 | QString m_api; 59 | bool m_ready; 60 | int m_timerID; 61 | }; 62 | 63 | #endif // MYMODEL_H 64 | -------------------------------------------------------------------------------- /src/weatherdata.cpp: -------------------------------------------------------------------------------- 1 | #include "weatherdata.h" 2 | 3 | IndexData::IndexData(QObject *parent) 4 | : QObject(parent), 5 | m_descript("未知"), 6 | m_tipt("未知"), 7 | m_title("未知"), 8 | m_state("未知") 9 | { 10 | 11 | } 12 | 13 | IndexData::~IndexData() 14 | { 15 | 16 | } 17 | 18 | QString IndexData::descript() const 19 | { 20 | return m_descript; 21 | } 22 | 23 | QString IndexData::tipt() const 24 | { 25 | return m_tipt; 26 | } 27 | 28 | QString IndexData::title() const 29 | { 30 | return m_title; 31 | } 32 | 33 | QString IndexData::state() const 34 | { 35 | return m_state; 36 | } 37 | 38 | void IndexData::setDescript(const QString &arg) 39 | { 40 | if (arg != m_descript) 41 | { 42 | m_descript = arg; 43 | emit descriptChanged(); 44 | } 45 | } 46 | 47 | void IndexData::setTipt(const QString &arg) 48 | { 49 | if (arg != m_tipt) 50 | { 51 | m_tipt = arg; 52 | emit tiptChanged(); 53 | } 54 | } 55 | 56 | void IndexData::setTitle(const QString &arg) 57 | { 58 | if (arg != m_title) 59 | { 60 | m_title = arg; 61 | emit titleChanged(); 62 | } 63 | } 64 | 65 | void IndexData::setState(const QString &arg) 66 | { 67 | if (arg != m_state) 68 | { 69 | m_state = arg; 70 | emit stateChanged(); 71 | } 72 | } 73 | 74 | 75 | WeatherData::WeatherData(QObject *parent) 76 | : QObject(parent), 77 | m_date("未知"), 78 | m_dayPicture(""), 79 | m_nightPicture(""), 80 | m_weather("未知"), 81 | m_wind("未知"), 82 | m_maxTemperature(0), 83 | m_minTemperature(0) 84 | { 85 | 86 | } 87 | 88 | WeatherData::~WeatherData() 89 | { 90 | 91 | } 92 | 93 | QString WeatherData::date() const 94 | { 95 | return m_date; 96 | } 97 | 98 | QString WeatherData::dayPicture() const 99 | { 100 | return m_dayPicture; 101 | } 102 | 103 | QString WeatherData::nightPicture() const 104 | { 105 | return m_nightPicture; 106 | } 107 | 108 | QString WeatherData::weather() const 109 | { 110 | return m_weather; 111 | } 112 | 113 | QString WeatherData::wind() const 114 | { 115 | return m_wind; 116 | } 117 | 118 | int WeatherData::maxTemperature() const 119 | { 120 | return m_maxTemperature; 121 | } 122 | 123 | int WeatherData::minTemperature() const 124 | { 125 | return m_minTemperature; 126 | } 127 | 128 | void WeatherData::setDate(const QString &arg) 129 | { 130 | if (arg != m_date) 131 | { 132 | m_date = arg; 133 | emit dateChanged(); 134 | } 135 | } 136 | 137 | void WeatherData::setDayPicture(const QString &arg) 138 | { 139 | if (arg != m_dayPicture) 140 | { 141 | m_dayPicture = arg; 142 | emit dayPictureChanged(); 143 | } 144 | } 145 | 146 | void WeatherData::setNightPicture(const QString &arg) 147 | { 148 | if (arg != m_nightPicture) 149 | { 150 | m_nightPicture = arg; 151 | emit nightPictureChanged(); 152 | } 153 | } 154 | 155 | void WeatherData::setWeather(const QString &arg) 156 | { 157 | if (arg != m_weather) 158 | { 159 | m_weather = arg; 160 | emit weatherChanged(); 161 | } 162 | } 163 | 164 | void WeatherData::setWind(const QString &arg) 165 | { 166 | if (arg != m_wind) 167 | { 168 | m_wind = arg; 169 | emit windChanged(); 170 | } 171 | } 172 | 173 | void WeatherData::setMaxTemperature(int arg) 174 | { 175 | if (arg != m_maxTemperature) 176 | { 177 | m_maxTemperature = arg; 178 | emit maxTemperatureChanged(); 179 | } 180 | } 181 | 182 | void WeatherData::setMinTemperature(int arg) 183 | { 184 | if (arg != m_minTemperature) 185 | { 186 | m_minTemperature = arg; 187 | emit minTemperatureChanged(); 188 | } 189 | } 190 | -------------------------------------------------------------------------------- /src/weatherdata.h: -------------------------------------------------------------------------------- 1 | #ifndef WEATHERDATA_H 2 | #define WEATHERDATA_H 3 | #include 4 | 5 | class IndexData : public QObject 6 | { 7 | Q_OBJECT 8 | 9 | Q_PROPERTY(QString descript READ descript WRITE setDescript NOTIFY descriptChanged) 10 | Q_PROPERTY(QString tipt READ tipt WRITE setTipt NOTIFY tiptChanged) 11 | Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged) 12 | Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged) 13 | 14 | public: 15 | IndexData(QObject *parent = nullptr); 16 | ~IndexData(); 17 | 18 | QString descript() const; 19 | QString tipt() const; 20 | QString title() const; 21 | QString state() const; 22 | 23 | public slots: 24 | void setDescript(const QString &arg); 25 | void setTipt(const QString &arg); 26 | void setTitle(const QString &arg); 27 | void setState(const QString &arg); 28 | 29 | signals: 30 | void descriptChanged(); 31 | void tiptChanged(); 32 | void titleChanged(); 33 | void stateChanged(); 34 | 35 | private: 36 | QString m_descript; 37 | QString m_tipt; 38 | QString m_title; 39 | QString m_state; 40 | }; 41 | 42 | class WeatherData : public QObject 43 | { 44 | Q_OBJECT 45 | 46 | Q_PROPERTY(QString date READ date WRITE setDate NOTIFY dateChanged) 47 | Q_PROPERTY(QString dayPicture READ dayPicture WRITE setDayPicture NOTIFY dayPictureChanged) 48 | Q_PROPERTY(QString nightPicture READ nightPicture WRITE setNightPicture NOTIFY nightPictureChanged) 49 | Q_PROPERTY(QString weather READ weather WRITE setWeather NOTIFY weatherChanged) 50 | Q_PROPERTY(QString wind READ wind WRITE setWind NOTIFY windChanged) 51 | Q_PROPERTY(int maxTemperature READ maxTemperature WRITE setMaxTemperature NOTIFY maxTemperatureChanged) 52 | Q_PROPERTY(int minTemperature READ minTemperature WRITE setMinTemperature NOTIFY minTemperatureChanged) 53 | 54 | public: 55 | WeatherData(QObject *parent = nullptr); 56 | ~WeatherData(); 57 | 58 | QString date() const; 59 | QString dayPicture() const; 60 | QString nightPicture() const; 61 | QString weather() const; 62 | QString wind() const; 63 | int maxTemperature() const; 64 | int minTemperature() const; 65 | 66 | public slots: 67 | void setDate(const QString &arg); 68 | void setDayPicture(const QString &arg); 69 | void setNightPicture(const QString &arg); 70 | void setWeather(const QString &arg); 71 | void setWind(const QString &arg); 72 | void setMaxTemperature(int arg); 73 | void setMinTemperature(int arg); 74 | 75 | signals: 76 | void dateChanged(); 77 | void dayPictureChanged(); 78 | void nightPictureChanged(); 79 | void weatherChanged(); 80 | void windChanged(); 81 | void maxTemperatureChanged(); 82 | void minTemperatureChanged(); 83 | 84 | private: 85 | QString m_date; 86 | QString m_dayPicture; 87 | QString m_nightPicture; 88 | QString m_weather; 89 | QString m_wind; 90 | int m_maxTemperature; 91 | int m_minTemperature; 92 | }; 93 | 94 | #endif // WEATHERDATA_H 95 | -------------------------------------------------------------------------------- /weather.pro: -------------------------------------------------------------------------------- 1 | QT += core qml network positioning widgets 2 | 3 | CONFIG += c++11 4 | 5 | TARGET = Weather 6 | 7 | TEMPLATE = app 8 | 9 | SOURCES += src/main.cpp \ 10 | src/myjsonparse.cpp \ 11 | src/mymodel.cpp \ 12 | src/weatherdata.cpp 13 | 14 | # The following define makes your compiler emit warnings if you use 15 | # any feature of Qt which as been marked deprecated (the exact warnings 16 | # depend on your compiler). Please consult the documentation of the 17 | # deprecated API in order to know how to port your code away from it. 18 | DEFINES += QT_DEPRECATED_WARNINGS 19 | 20 | # You can also make your code fail to compile if you use deprecated APIs. 21 | # In order to do so, uncomment the following line. 22 | # You can also select to disable deprecated APIs only up to a certain version of Qt. 23 | #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 24 | 25 | HEADERS += src/myjsonparse.h \ 26 | src/mymodel.h \ 27 | src/weatherdata.h 28 | 29 | RESOURCES += qml.qrc 30 | --------------------------------------------------------------------------------