#はじめに
OpenWeatherMapでデータを取得してPySimpleGUIで天気を表示しました。
#OpenWeatherMapについて
実装コードにはOpenWeatherMapのAPIを利用しています。
利用するにはAPIkeyの取得が必要です。
取得方法については以下にまとめられています。
無料天気予報APIのOpenWeatherMapを使ってみる
#実装コード
from tkinter import font
import requests
import json
import PySimpleGUI as sg
class MyWeather:
API_Endpoint = "http://api.openweathermap.org/data/2.5/forecast"
API_Key = "あなたのkeyを入力"
location = "Osaka"
query = {"q": location, "APPID": API_Key, "lang": "ja"}
data = requests.get(API_Endpoint, params=query).json()
WEATHER_LENGTH = 10#天気を返す数 三時間ごと
def __init__(self):
pass
def getTime(self, num):
# 時間 19XX-01-01 00:00:00のように返ってくる
time = self.data["list"][num]["dt_txt"]
return time
def getIconID(self,num):#デバッグ用
weather = self.data["list"][num]["weather"]
icon = weather[0]["icon"]
return icon
def getWeather(self, num): # 天気アイコンのパスを返す
sunnyImage = "weather/icon/sunny_icon.png"
fewCloudsImage = "weather/icon/fewClouds_icon.png"
brokenCloudsImage = "weather/icon/brokenClouds_icon.png"
cloudyImage = "weather/icon/cloudy_icon.png"
rainyImgae = "weather/icon/rainy_icon.png"
snowImage = "weather/icon/snow_icon.png"
thunderImage = "weather/icon/thunder_icon.png"
errorImage = "weather/icon/error_icon.png"
weather = self.data["list"][num]["weather"]
icon = weather[0]["icon"]
if icon == "01n" or icon == "01d":
return sunnyImage
elif icon == "02d" or icon == "02n":
return fewCloudsImage
elif icon == "03d" or icon == "03n":
return cloudyImage
elif icon == "04d" or icon == "04n":
return brokenCloudsImage
elif icon == "09d" or icon == "09n":
return rainyImgae
elif icon == "10d" or icon == "10n":
return rainyImgae
elif icon == "11d" or icon == "11n":
return thunderImage
elif icon == "13d" or icon == "13n":
return snowImage
else:
return errorImage
def drawScreen(self):
sg.theme("Python")#GUIの配色
title = [
[sg.Text(str(self.getTime(0))+'~' +
str(self.getTime(self.WEATHER_LENGTH-1)+'の'+self.location+'の'+'天気'), font=('メイリオ', 20))]
]
titleFrame = sg.Frame(
'', [[sg.Column(title, justification='c')]], size=(self.WEATHER_LENGTH*150, 100))
timeText = [[]]
timeFrame = [[]]
timeFrameBig = [[]]
for i in range(self.WEATHER_LENGTH):
time = str(self.getTime(i).split(' ', 1)[1])
time = time.split(':', 1)[0]
timeText = [sg.Column
([[sg.Text(time+'時', font=('メイリオ', 30))]], justification='c')]
timeFrame[0].extend(
[sg.Frame('', [timeText], size=(150, 100))])
timeFrameBig = [[sg.Frame('', [timeFrame[0]])]]
icon = [[]]
iconFrame = [[]]
iconFrameBig = [[]]
for i in range(self.WEATHER_LENGTH):
icon = [
sg.Column([[sg.Image(self.getWeather(i))]], justification='c')]
iconFrame[0].extend(
[sg.Frame('', [icon], size=(150, 120))])
iconFrameBig = [[sg.Frame('', [iconFrame[0]])]]
layout = [[titleFrame], [timeFrameBig], [iconFrameBig]]
window = sg.Window("お天気", layout, resizable=True)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
window.close()
def main():
hoge = MyWeather()
hoge.drawScreen()
return 0
if __name__ == "__main__":
main()
##API部(OpenWeatherMap部)
class MyWeather:
API_Endpoint = "http://api.openweathermap.org/data/2.5/forecast"
API_Key = "あなたのkeyを入力"
location = "Osaka"
query = {"q": location, "APPID": API_Key, "lang": "ja"}
data = requests.get(API_Endpoint, params=query).json()
classの先頭でAPIに渡す情報を作っています。
queryの内容やAPIの返答内容(dataの中身)はOpenWeatherMapのFAQみたいなところに書いてあります。
参考にした記事:APIの仕組みが分かる・使いこなせる人材になれる記事(Pythonコード付き)
##描画部(PySimpleGUI部)
def drawScreen(self):
sg.theme("Python")#GUIの配色
title = [
[sg.Text(str(self.getTime(0))+'~' +
str(self.getTime(self.WEATHER_LENGTH-1)+'の'+self.location+'の'+'天気'), font=('メイリオ', 20))]
]
titleFrame = sg.Frame(
'', [[sg.Column(title, justification='c')]], size=(self.WEATHER_LENGTH*150, 100))
timeText = [[]]
timeFrame = [[]]
timeFrameBig = [[]]
for i in range(self.WEATHER_LENGTH):
time = str(self.getTime(i).split(' ', 1)[1])
time = time.split(':', 1)[0]
timeText = [sg.Column
([[sg.Text(time+'時', font=('メイリオ', 30))]], justification='c')]
timeFrame[0].extend(
[sg.Frame('', [timeText], size=(150, 100))])
timeFrameBig = [[sg.Frame('', [timeFrame[0]])]]
icon = [[]]
iconFrame = [[]]
iconFrameBig = [[]]
for i in range(self.WEATHER_LENGTH):
icon = [
sg.Column([[sg.Image(self.getWeather(i))]], justification='c')]
iconFrame[0].extend(
[sg.Frame('', [icon], size=(150, 120))])
iconFrameBig = [[sg.Frame('', [iconFrame[0]])]]
layout = [[titleFrame], [timeFrameBig], [iconFrameBig]]
window = sg.Window("お天気", layout, resizable=True)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
window.close()
描画部分です。
layout = [[titleFrame], [timeFrameBig], [iconFrameBig]]
window = sg.Window("お天気", layout, resizable=True)
while True:
event, values = window.read()
if event == sg.WIN_CLOSED:
break
layout内にGUIのレイアウトを記述します。レイアウトについては以下の記事が参考になると思います。
pythonでも簡単にGUIは作れる
PySimpleGUIのレイアウトの設定方法
###タイトル部
def drawScreen(self):
sg.theme("Python")#GUIの配色
title = [
[sg.Text(str(self.getTime(0))+'~' + #self.getTime(i)の返り値→ 19XX-YY-ZZ xx:yy:zz
str(self.getTime(self.WEATHER_LENGTH-1)+'の'+self.location+'の'+'天気'), font=('メイリオ', 20))]
]
titleFrame = sg.Frame(
'', [[sg.Column(title, justification='c')]], size=(self.WEATHER_LENGTH*150, 100))
赤枠の部分です。sg.Text単体では文章を中央揃えにできなさそうなので、sg.Columnを介して中央揃えにしています。
###時間部
timeText = [[]]
timeFrame = [[]]
timeFrameBig = [[]]
for i in range(self.WEATHER_LENGTH):#self.getTime(i)の返り値→ 19XX-YY-ZZ xx:yy:zz
time = str(self.getTime(i).split(' ', 1)[1])#xx:yy:zz
time = time.split(':', 1)[0]#xx
timeText = [sg.Column
([[sg.Text(time+'時', font=('メイリオ', 30))]], justification='c')]
timeFrame[0].extend(
[sg.Frame('', [timeText], size=(150, 100))])
timeFrameBig = [[sg.Frame('', [timeFrame[0]])]]
赤枠の部分です。リストの入れ子構造を間違えてエラーが頻発しました。
ここもsg.Columnで中央揃えにしています。
###アイコン部
icon = [[]]
iconFrame = [[]]
iconFrameBig = [[]]
for i in range(self.WEATHER_LENGTH):
icon = [
sg.Column([[sg.Image(self.getWeather(i))]], justification='c')]#self.getWeatherの返り値は画像のパス
iconFrame[0].extend(
[sg.Frame('', [icon], size=(150, 120))])
iconFrameBig = [[sg.Frame('', [iconFrame[0]])]]
赤枠の部分です。self.getWeather(i)は画像のパスを返します。
####getWeather
def getWeather(self, num): # 天気アイコンのパスを返す
sunnyImage = "weather/icon/sunny_icon.png"
fewCloudsImage = "weather/icon/fewClouds_icon.png"
brokenCloudsImage = "weather/icon/brokenClouds_icon.png"
cloudyImage = "weather/icon/cloudy_icon.png"
rainyImgae = "weather/icon/rainy_icon.png"
snowImage = "weather/icon/snow_icon.png"
thunderImage = "weather/icon/thunder_icon.png"
errorImage = "weather/icon/error_icon.png"
weather = self.data["list"][num]["weather"]
icon = weather[0]["icon"]
if icon == "01n" or icon == "01d":
return sunnyImage
elif icon == "02d" or icon == "02n":
return fewCloudsImage
elif icon == "03d" or icon == "03n":
return cloudyImage
elif icon == "04d" or icon == "04n":
return brokenCloudsImage
elif icon == "09d" or icon == "09n":
return rainyImgae
elif icon == "10d" or icon == "10n":
return rainyImgae
elif icon == "11d" or icon == "11n":
return thunderImage
elif icon == "13d" or icon == "13n":
return snowImage
else:
return errorImage
天気アイコンはicoon-mono 様のものをお借りしました。
また、OpenWetherMapに詳細なアイコンのIDがあります。