前面我们做了一个简单的视窗应用,已经对 PySimpleGUI 有了大概的 “感觉”,做出来的东西别管多简单吧,起码有点 “产品” 的意思了。
其实这个简单的作品,已经具备了一个典型视窗的绝大多数要素:
- 蓝图,上一节中的 layout,它是一个 成员为 list 的 list,定义了窗口的长相;
- window;
- 响应用户事件,那个 event,希望你还记得它;
- 获得用户输入,当然是上一节里的 values。
event 和 values 只是约定的名称,你当然可以将 window.read() 的返回值解包为其他变量。
约定为 event、values,我们就都明白说的是 read 函数返回值的第一项和第二项。
再罗列一下目前已经实用过的组件:
图中有些内容有点多,再罗列一下:
- Text,显示文本标签;
- Input,输入框
- Button,按钮
基于这些简单素材,就足够我们制作一些有相当实用价值的工具了。
一起加油,做个天气预报小工具。
你也可以在线运行本期代码
https://repl.it/@alvendarthy/PySimpleGUIDemo3
绘制蓝图
依照惯例,第一步确定天气预报小程序需要什么信息:
- 城市(只做国内主要城市),用熟悉的 Input;
- 一个按钮,点击查询天气;
- 还需要一个地方展示天气,依然使用 Input,将天气填进去就好。
- 在两个输入框左侧,还会有两个 Text 作为输入框的标题。
总共 5 个组件,其实都是比较熟悉的组件了,还蛮简单的。
按照自己的审美,绘制一个效果图,你可以用纸笔绘制。希望你可以将图中的组件类型标注出来。
参考这个图纸,可以开始完成一部分代码,实现蓝图,并把它显示出来。
如果你用的是 https://repl.it/ 在线编程环境,它不支持中文,所有显示内容必须是英文。
import PySimpleGUI as sg
# 让所有文本居中
sg.SetOptions(text_justification='center')
layout = [
[ sg.Text("City", size = (20, 1)), sg.Input(key = "-CITY-") ],
[ sg.Text("Weather", size = (20, 1)), sg.Input(key = "-WEATHER-") ],
[ sg.Button("Submit")]
]
window = sg.Window("Weather App", layout)
event, values = window.read()
print(event, values)
window.close()
注意到 Text 被指定了 size 参数,用一个 tuple 表示组件的大小。size = (20, 1) 表示 20 长,高为 1,单位不详。
点击 run 就会看到界面了,
在视图窗口中 City 栏输入 “Beijing”,点击 Submit,会在下面的命令行输出:
Submit {'-CITY-': 'Beijing', '-WEATHER-': ''}
不出意外的话,城市名称通过 values["-CITY-"] 就能得到。
获取天气信息
下来的问题就是怎么获得天气预报了,计算机本身是不可能知道天气的,怎么办呢?上网啊!通过互联网可以找到开放的天气预报接口。
什么是接口
不同于面向用户的网址(URL),接口返回的是单纯的数据,而非花花绿绿的网页。这样的 URL 就是接口,面向的是开发人员,而非最终用户。如果你开始接触网络接口,恭喜你已经是开发者的一员了。
我已经为大家找到两个接口可用:
通过城市名字获得天气数据(json)
http://wthrcdn.etouch.cn/weather_mini?city=北京市通过城市ID获得天气数据(json)
http://wthrcdn.etouch.cn/weather_mini?citykey=101010100
你可以将上面的 URL 在浏览器中打开,数据会被下载为文件,打开会看到:
它们就是网络接口返回的数据,不是网页而是单纯的数据,这样的数据格式称为 Json。
将内容复制到在线 json 格式化工具 https://www.json.cn/ 左侧窗口,数据会更易读:
{
"data":{
"yesterday":{
"date":"2日星期一",
"high":"高温 4℃",
"fx":"西南风",
"low":"低温 -4℃",
"fl":"<![CDATA[3-4级]]>",
"type":"晴"
},
"city":"北京",
"forecast":[
{
"date":"3日星期二",
"high":"高温 8℃",
"fengli":"<![CDATA[<3级]]>",
"low":"低温 -4℃",
"fengxiang":"西南风",
"type":"晴"
},
{
"date":"4日星期三",
"high":"高温 8℃",
"fengli":"<![CDATA[<3级]]>",
"low":"低温 -5℃",
"fengxiang":"西南风",
"type":"晴"
},
{
"date":"5日星期四",
"high":"高温 3℃",
"fengli":"<![CDATA[<3级]]>",
"low":"低温 -6℃",
"fengxiang":"东风",
"type":"晴"
},
{
"date":"6日星期五",
"high":"高温 3℃",
"fengli":"<![CDATA[<3级]]>",
"low":"低温 -6℃",
"fengxiang":"西南风",
"type":"晴"
},
{
"date":"7日星期六",
"high":"高温 4℃",
"fengli":"<![CDATA[<3级]]>",
"low":"低温 -6℃",
"fengxiang":"东北风",
"type":"晴"
}
],
"ganmao":"昼夜温差很大,易发生感冒,请注意适当增减衣服,加强自我防护避免感冒。",
"wendu":"8"
},
"status":1000,
"desc":"OK"
}
这样清晰多了吧,看起来很像 Python 中的字典是吧!这就是网络接口返回的数据。如果这些数据保存在 ret 变量中,那肯定可以通过 ret["data"]["forecast"][0] 获得明天的天气了!没错,但是需要先借助 json 库将它转换为 Python 字典才行,现在它还是 String。
我们的小程序怎么获得这个网络接口的数据呢?感谢 Python 强大的生态,request 库可以帮助我们,不借助浏览器也能访问网络接口。
总结
根据上面掌握的信息,就有了获取天气的基本思路
- 用 requests 库请求网络接口;
- 用 json 库将返回的内容转换为 Python 字典;
- 访问字典得到天气预报
- 将天气字符串显示到视窗中的 Input 中,到时候会调用 Input 组件的 update 函数。
做到这一步,已经可以根据图纸实现包含 5 个组件的窗口,我们离成功只有一步之遥了!
下面是 requests 库的文档,可以提前了解基本用法,预习是个好习惯。
http://2.python-requests.org/zh_CN/latest/user/quickstart.html
劳逸结合,不要太累,明天继续咯!