python3GUI--天气预报小工具By:PyQt5(附源码)
文章目錄
- 一.準備工作
- 二.預覽
- 1.啟動
- 2.添加城市
- 三.設計流程
- 1.UI設計(草圖)
- 2.UI設計(QT設計師)
- 3.解釋
- 四.源代碼
- 五.總結
之前用tk寫過一款python3GUI–天氣預報小工具實現了所在天氣定位,以及指定城市天氣預報的查詢,這次使用PyQt5在之前tk的基礎上加以改進,雖然功能沒有新的增加,但是軟件整體速度上有明顯的變化,開整吧。
一.準備工作
基于PyQt5的QT設計師,安裝、配置詳見:
PyCharm安裝PyQt5及其工具(Qt Designer、PyUIC、PyRcc)詳細教程
二.預覽
1.啟動
啟動后,會自動定位當前所在城市,展示所在城市前后五天的天氣信息。
2.添加城市
點擊“添加城市”,向主界面添加城市,遂展示所選城市天氣信息,每個選項卡是能夠關閉的,工具欄可以自由移動。
三.設計流程
天氣數據還是基于spider,重點在于界面的設計以及信號和槽的使用。
1.UI設計(草圖)
整體由QToolBar、QTabWidget、QTableWidget、Qlabel組成
2.UI設計(QT設計師)
3.解釋
這里解釋一下,為什么有些組件最后沒有展示:首次打開軟件時,軟件進行定位,會顯示一張圖片一個進度條以及一個帶loading的標簽,這時候QTableWidget是隱藏的,整體布局為垂直布局,當定位完成后,將QTableWidget設為可見并載入數據,loading結束,隱藏圖片、進度條、以及加載提示,整體仍為垂直布局。
四.源代碼
這里放的是UI與爬蟲的交互代碼
#-*-coding:utf-8-*- import sys import datetime import threading import webbrowser from PyQt5.uic import * from PyQt5.QtGui import * from PyQt5.QtCore import * from PyQt5 import QtWidgets from PyQt5.QtWidgets import * from PyQt5.QtCore import Qt as qqt from Weather_Spider import Weather_Get import add_city import weather""" 天氣信息刷新時,label不能更新**已解決** “添加城市”窗口,關閉后,主窗口不可用setEnable(True)**未解決** **0914已解決** 使用自定義信號槽#天氣信息待加載,與label不能對應______________________**已解決**熱鍵注冊 """ class add_city_window(QWidget):Signal_parp = pyqtSignal(bool)def __init__(self):# 信號的定義super().__init__()#這里有些不解,為什么調用時,要用兩側add_uiself.add_ui=add_city.Ui_add_city_window()self.add_ui.setupUi(self)def closeEvent(self, event):self.close()self.Signal_parp.emit(True)class Weather_Report(QMainWindow):Signal_parp = pyqtSignal(str)def __init__(self):super().__init__()self.first_start_flag=Trueself.tab_index=0self.label_widget_list=[]self.table_widget_list=[]self.ui =weather.Ui_MainWindow()self.ui.setupUi(self)self.setFixedSize(self.width(), self.height())#禁止最大化self.setFixedSize(695, 445) # 天氣信息加載成功之后,窗口的大小self.adjustSize()self.ui.tabWidget.hide()self.ui.action_open_China_weather.setEnabled(False)self.ui.action_add_city.setEnabled(False)self.W=Weather_Get()self.current_china_weather_url=''self.city_number_list=[]self.city_list=[]self.ui.action_open_China_weather.triggered.connect(self.open_china_weather_web)self.ui.actiont_quit_window.triggered.connect(self.close)self.ui.action_refresh.triggered.connect(self.refreash_weather_infos)self.ui.action_about_author.triggered.connect(self.show_about_author)self.ui.action_add_city.triggered.connect(self.do_select_city)self.ui.tabWidget.tabCloseRequested.connect(self.close_tab)self.ui.tabWidget.currentChanged.connect(self.change_index)self.thread_it(self.show_local_weather)def change_main_ui_status(self, status):self.setEnabled(status)def show_local_weather(self):'''展示定位天氣信息:return:'''self.ui.label_weather_infos.setText('正在刷新......')self.ui.tableWidget.clearContents()try:if self.first_start_flag:city,item,number=self.W.get_local_weather()self.local_city_number=numberself.local_city_=cityelse:item=self.W.get_weather(self.local_city_number)city=self.local_city_number=self.local_city_numberself.ui.tabWidget.setTabText(0,city) #將默認的定位更改為當前所在城市名datas = item['recent']self.ui.action_open_China_weather.setEnabled(True)self.ui.action_add_city.setEnabled(True)self.ui.label_loading_pic.hide()self.ui.label_loading_now.hide()self.ui.BlueProgressBar.hide()self.ui.tabWidget.setVisible(True)self.ui.label_weather_infos.setVisible(True)for index,data in enumerate(datas):newItem = QTableWidgetItem(data["日期"])newItem.setTextAlignment(Qt.AlignCenter )self.ui.tableWidget.setItem(index, 0, newItem)newItem = QTableWidgetItem(data["天氣"])newItem.setTextAlignment(Qt.AlignCenter )self.ui.tableWidget.setItem(index, 1, newItem)newItem = QTableWidgetItem(data["風力風向"])newItem.setTextAlignment(Qt.AlignCenter)self.ui.tableWidget.setItem(index, 2, newItem)newItem = QTableWidgetItem(data["最低氣溫"])newItem.setTextAlignment(Qt.AlignCenter )self.ui.tableWidget.setItem(index, 3, newItem)newItem = QTableWidgetItem(data["最高氣溫"])newItem.setTextAlignment(Qt.AlignCenter)self.ui.tableWidget.setItem(index, 4, newItem)self.ui.tableWidget.setColumnWidth(0, 160)self.ui.tableWidget.setColumnWidth(4, 125)now_time = str(datetime.datetime.now()).split('.')[0].split(' ')[-1]self.ui.label_weather_infos.setText(f'今天:{self.show_date()}\n當前所在地區:{city}\n當前氣溫:{item["now"]}({now_time}更新)\n感冒指數:{item["ganmao"]}')#將定位城市加入 已展示城市列表self.location中self.current_china_weather_url= f'http://www.weather.com.cn/weather/{number}.shtml'if self.first_start_flag:self.city_number_list.append(number)self.city_list.append(city)self.first_start_flag=Falseexcept TypeError:QMessageBox.warning(self,'錯誤','天氣信息加載失敗!')self.statusBar().showMessage('天氣信息加載失敗!', 3000)self.s2.entryconfig('添加城市', state='normal')def show_date(self):"""展示日期信息,便于天氣展示:return:"""date = str(datetime.date.today())year,month,day=date.split('-')week_day_dict = {0: '星期一',1: '星期二',2: '星期三',3: '星期四',4: '星期五',5: '星期六',6: '星期日 ',}now=datetime.datetime.now()date_index = now.weekday()date_time=f'{year}年{month}月{day}日 {week_day_dict[date_index]}'return date_timedef do_select_city(self):#選擇省份 城市 所在地self.setEnabled(False)self.add_ui=add_city_window()self.add_ui.Signal_parp.connect(self.change_main_ui_status)self.add_ui.setFixedSize(self.add_ui.width(), self.add_ui.height())#禁止最大化provences=self.W.get_provinces()self.add_ui.add_ui.comboBox_provence.addItem('--請選擇--')self.add_ui.add_ui.comboBox_provence.addItems(provences)self.add_ui.add_ui.comboBox_provence.currentIndexChanged.connect(self.get_citys)self.add_ui.add_ui.comboBox_city.currentIndexChanged.connect(self.get_regions)self.add_ui.add_ui.pushButton_add_the_city.clicked.connect(self.do_add_city)self.add_ui.show()def closeEvent(self,event):reply = QMessageBox.question(self, '關閉', "確定要退出嗎?",QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes)# 判斷返回值,如果點擊的是Yes按鈕,我們就關閉組件和應用,否則就忽略關閉事件if reply == QMessageBox.Yes:event.accept()else:event.ignore()def get_citys(self):self.add_ui.add_ui.comboBox_city.clear()self.add_ui.add_ui.comboBox_region.clear()self.curr_provence=self.add_ui.add_ui.comboBox_provence.currentText()ciyies=self.W.get_cities(self.curr_provence)self.add_ui.add_ui.comboBox_city.addItems(ciyies)def get_regions(self):try:self.add_ui.add_ui.comboBox_region.clear()self.curr_city=self.add_ui.add_ui.comboBox_city.currentText()ciyies=self.W.get_regions(self.curr_provence,self.curr_city)self.add_ui.add_ui.comboBox_region.addItems(ciyies)except KeyError:passdef do_add_city(self):if self.add_ui.add_ui.comboBox_provence.currentText()=='--請選擇--':QMessageBox.warning(self,'警告','請選擇城市!')else:self.curr_region=self.add_ui.add_ui.comboBox_region.currentText()self.curr_city_no=0if self.curr_region!='':self.curr_city_data=self.curr_provence+self.curr_city+self.curr_regionself.curr_city_no=self.W.get_city_id_by_add(self.curr_provence,self.curr_city,self.curr_region)else:self.curr_city_data=self.curr_provence+self.curr_cityself.curr_city_no=self.W.get_city_id_by_add(self.curr_provence,self.curr_city)if self.curr_city_no==0:QMessageBox.information(self,"提示",'未找到相關城市天氣信息,請嘗試更換城市!')else:if self.curr_city_no in self.city_number_list:QMessageBox.warning(self, "警告", '此城市已經添加,請勿重復添加!')else:self.tab=QWidget(self)self.ui.tabWidget.addTab(self.tab,self.curr_city_data)tble_widget_new=QTableWidget(self.ui.tabWidget)tble_widget_new.setEnabled(True)tble_widget_new.setContextMenuPolicy(qqt.NoContextMenu)#沒有右鍵菜單tble_widget_new.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustToContentsOnFirstShow)#自動添加滾動條tble_widget_new.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)#不可編輯tble_widget_new.setAlternatingRowColors(True)tble_widget_new.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)#選擇模式:單選tble_widget_new.setSelectionBehavior(QtWidgets.QAbstractItemView.SelectRows)#選擇行為:整行選擇tble_widget_new.setTextElideMode(qqt.ElideMiddle)#省略號出現在長文本中間tble_widget_new.setShowGrid(True)#顯示網格tble_widget_new.setGridStyle(qqt.SolidLine)#網格風格tble_widget_new.setWordWrap(True)tble_widget_new.setRowCount(5)tble_widget_new.setColumnCount(5)tble_widget_new.horizontalHeader().setCascadingSectionResizes(False)tble_widget_new.horizontalHeader().setDefaultSectionSize(95)tble_widget_new.horizontalHeader().setMinimumSectionSize(30)tble_widget_new.verticalHeader().setVisible(False)tble_widget_new.verticalHeader().setCascadingSectionResizes(False)tble_widget_new.verticalHeader().setDefaultSectionSize(36)tble_widget_new.verticalHeader().setMinimumSectionSize(30)tble_widget_new.verticalHeader().setSortIndicatorShown(False)tble_widget_new.verticalHeader().setStretchLastSection(True)tble_widget_new.horizontalHeader().setStretchLastSection(True)tble_widget_new.setColumnWidth(0, 160)tble_widget_new.setColumnWidth(4, 125)tble_widget_new.setHorizontalHeaderLabels(['日期', '天氣', '風向風力', '最低氣溫', '最高氣溫'])new_label=QLabel(self)# 渲染到頁面Layout = QVBoxLayout(self.tab)Layout.setContentsMargins(0, 0, 0, 0)self.setEnabled(True)self.add_ui.close()#關閉“添加城市”窗口weather_infos=self.W.get_weather(self.curr_city_no)datas = weather_infos['recent']for index, data in enumerate(datas):newItem = QTableWidgetItem(data["日期"])newItem.setTextAlignment(Qt.AlignCenter)tble_widget_new.setItem(index, 0, newItem)newItem = QTableWidgetItem(data["天氣"])newItem.setTextAlignment(Qt.AlignCenter)tble_widget_new.setItem(index, 1, newItem)newItem = QTableWidgetItem(data["風力風向"])newItem.setTextAlignment(Qt.AlignCenter)tble_widget_new.setItem(index, 2, newItem)newItem = QTableWidgetItem(data["最低氣溫"])newItem.setTextAlignment(Qt.AlignCenter)tble_widget_new.setItem(index, 3, newItem)newItem = QTableWidgetItem(data["最高氣溫"])newItem.setTextAlignment(Qt.AlignCenter)tble_widget_new.setItem(index, 4, newItem)tble_widget_new.setColumnWidth(0, 160)tble_widget_new.setColumnWidth(4, 162)now_time = str(datetime.datetime.now()).split('.')[0].split(' ')[-1]new_label.setText(f'今天:{self.show_date()}\n當前所選地區:{self.curr_city_data}\n當前氣溫:{weather_infos["now"]}({now_time}更新)\n感冒指數:{weather_infos["ganmao"]}')# 將定位城市加入 已展示城市列表self.location中Layout.addWidget(tble_widget_new)Layout.addWidget(new_label)self.label_widget_list.append(new_label)self.table_widget_list.append(tble_widget_new)self.city_number_list.append(self.curr_city_no)self.city_list.append(self.curr_city)def thread_it(self,func,*args):'''防止線程沖突:param func::param args::return:'''t=threading.Thread(target=func,args=args)t.setDaemon(True)t.start()def refreash_weather_infos(self):if self.tab_index==0:self.ui.label_weather_infos.setText('正在刷新天氣信息......')self.thread_it(self.show_local_weather)else:curr_city_no=self.city_number_list[self.tab_index]table_widget=self.table_widget_list[self.tab_index-1]new_label=self.label_widget_list[self.tab_index-1]table_widget.clearContents()weather_infos = self.W.get_weather(curr_city_no)weather_data=weather_infos['recent']for index, data in enumerate(weather_data):newItem = QTableWidgetItem(data["日期"])newItem.setTextAlignment(Qt.AlignCenter)table_widget.setItem(index, 0, newItem)newItem = QTableWidgetItem(data["天氣"])newItem.setTextAlignment(Qt.AlignCenter)table_widget.setItem(index, 1, newItem)newItem = QTableWidgetItem(data["風力風向"])newItem.setTextAlignment(Qt.AlignCenter)table_widget.setItem(index, 2, newItem)newItem = QTableWidgetItem(data["最低氣溫"])newItem.setTextAlignment(Qt.AlignCenter)table_widget.setItem(index, 3, newItem)newItem = QTableWidgetItem(data["最高氣溫"])newItem.setTextAlignment(Qt.AlignCenter)table_widget.setItem(index, 4, newItem)now_time = str(datetime.datetime.now()).split('.')[0].split(' ')[-1]new_label.setText(f'今天:{self.show_date()}\n當前所選地區:{self.curr_city_data}\n當前氣溫:{weather_infos["now"]}({now_time}更新)\n感冒指數:{weather_infos["ganmao"]}')def open_china_weather_web(self):webbrowser.open(self.current_china_weather_url)def close_tab(self,index):if self.ui.tabWidget.count()>1:self.ui.tabWidget.removeTab(index)#同步更新兩個列表self.city_number_list.pop(index)self.city_list.pop(index)else:self.close()def change_index(self,index):"""tabwidget 索引發生改變觸發的事件,改變當前中國天氣URL地址:param index: 當前tab所選索引:return:"""self.current_china_weather_url= f'http://www.weather.com.cn/weather/{self.city_number_list[index]}.shtml'self.tab_index=indexdef show_about_author(self):QMessageBox.information(self,'關于','作者:懷淰メ\nBy:PyQT5')if __name__ == '__main__':app=QApplication(sys.argv)ui=Weather_Report()ui.show()sys.exit(app.exec_())五.總結
QT設計師是真的好用,幫助我少寫了很多的代碼,算了一下,這個界面大概少寫了300行代碼,大部分時間都花在了界面的設計以及界面交互槽函數的實現,對比tk,QT確實強大!今后我還要多加練習,實現更多復雜的功能!
軟件打包好,放在了藍奏云。思路、代碼方面有什么不足歡迎各位大佬指正、批評!能點個贊給我個鼓勵嗎?
總結
以上是生活随笔為你收集整理的python3GUI--天气预报小工具By:PyQt5(附源码)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Intra-LTE Handover :
- 下一篇: Linux系统删除Firefox,Lin