今
日
鸡
汤
解释春风无限恨,沉香亭北倚栏杆。
大家好,在昨天的文章中我们已经介绍了为什么以及如何基本使用PySimpleGUI
,并且对一些比较常用的元素(element)也有所了解。
本文将对基础版中的一些元素与新讲解的元素进行组合,构建一个图片查看系统与一个简易的计算机视觉系统(代码调用前置照相机)
作为PySimpleGUI
的进阶篇,我将分为以下两个部分讲解:
- 图片查看系统的构建
- 简易计算机视觉系统(cv)的构建
本次内容主要涉及的Python模块:
PySimpleGUI
os
cv2
图片查看系统的构建
1、代码与效果呈现
开门见山,先看最终效果和代码,后面再解读,在本节我们需要实现的就是如下图所示的一个图片查看系统,左边输入图片所在文件夹,就可以按顺序查看图片
下面为全部的源码,可以看到并不是很多,这也体现了我们之前说的简单性!
import PySimpleGUI as sg
import os.path
file_list_column = [
[
sg.Text("Image Folder"),
sg.In(size=(25, 1), enable_events=True, key="-FOLDER-"),
sg.FolderBrowse('浏览'),
],
[
sg.Listbox(
values=[], enable_events=True, size=(40, 20), key="-FILE LIST-"
)
],
]
image_viewer_column = [
[sg.Text("从左边图片列表中选择一张图片:")],
[sg.Text(size=(40, 1), key="-TOUT-")],
[sg.Image(key="-IMAGE-")],
]
layout = [
[
sg.Column(file_list_column),
sg.VSeperator(),
sg.Column(image_viewer_column),
]
]
window = sg.Window("图片查看系统", layout)
while True:
event, values = window.read()
if event == "Exit" or event == sg.WIN_CLOSED:
break
if event == "-FOLDER-":
folder = values["-FOLDER-"]
try:
file_list = os.listdir(folder)
except:
file_list = []
fnames = [
f
for f in file_list
if os.path.isfile(os.path.join(folder, f))
and f.lower().endswith((".png", ".gif"))
]
window["-FILE LIST-"].update(fnames)
elif event == "-FILE LIST-":
try:
filename = os.path.join(
values["-FOLDER-"], values["-FILE LIST-"][0]
)
window["-TOUT-"].update(filename)
window["-IMAGE-"].update(filename=filename)
except:
pass
window.close()
2、代码解读
首先先温故一下上篇基础章节的内容,默认端口下的PySimpleGUI
只对PNG、GIF等格式,而常见的JPG、TIFF格式是不能被其调用的。如果想调用的话可以用Python中的另一个库Pillow
来转换。
按照我们的构造GUI基本框架:
引入模块 创建元素并填充layout 创建窗体
import PySimpleGUI as sg
import os.path
file_list_column = [
[
sg.Text("Image Folder"),
sg.In(size=(25, 1), enable_events=True, key="-FOLDER-"),
sg.FolderBrowse('浏览'),
],
[
sg.Listbox(
values=[], enable_events=True, size=(40, 20), key="-FILE LIST-"
)
],
]
上述代码layout
中的第一个列表元素,是如下图的代码
代码中引入os
模块对文件夹进行调用,在创建一个垂直方向的元素嵌套列表file_list_column
,里面的元素如上图般放置。在嵌套列表里有4个元素:
Text
InputText
FolderBrowse
Listbox
其中代码中的In
等价于InputText
,在上节中有提及。总体来说,上述元素的功能就是打开图片所在文件夹和陈列所有图片信息。
Text
中写的"Image Folder"是一个标识,用来说明。
InputText
中先设置了框的大小是长25,宽1的单位长度。
enable_events
和key
两个参数是一起用的。这里的参数key
是GUI中非常重要的参数,是用来在整个GUI中鉴别特殊的元素的。比如此处中,定义了一个"-FOLDER-"的身份给-
InputText
这个元素。有了这个key
,你可以在循环事件中去调用它。学习过其他GUI库,诸如wxpython
、Tkinter
等,这个key
就像是用来绑定事件的函数一样。在面向对象语言中,这就像定义了一个类一般。但这些都是非常复杂的,而做的像key
这样的,足可以说明PySimpleGUI
的便利。单独来讲,key
是用来标记的,enable_events
就是用来控制元素对应事件循环中开始与结束,相当于执行元素中的事件。最后一个元素是
Listbox
,显而易见,这是用来展示所选文件列表中的所有照片路径的信息。你可以在这个列表中点击你想看的照片。对于这个列表箱子,你可以传递字符串列表来填充他。
Listbox
是一个列表箱子,顾名思义是一个列表类型的。在
Listbox
里面先设置了空的列表值,这是因为第一次打开图形交互页面时,由于你没有选择文件夹,所以对应的箱子是空的。和上面一样设置的key
与enable_events
标记了key
为"-FILE LIST-"与开启绑定事件功能,并且设置了(40,20)的大小。
接下里看layout中的第二个列表元素
image_viewer_column = [
[sg.Text("从左边图片列表中选择一张图片:")],
[sg.Text(size=(40, 1), key="-TOUT-")],
[sg.Image(key="-IMAGE-")],
]
这是如图的代码:
这里有三个元素:两个Text
、Image
第一个
Text
元素是说明让使用者在左边列表中选择一个想看的照片.第二个
Text
是显示已选择的图片基本信息,同时给予了key
为-TOUT-
,大小为(40,1)。第三个元素就是上节介绍的
Image
元素,给予了key
为-IMAGE-
的身份标识。可以看到这里没用到enable_events
,因为像图片这种,我们只需观看它,而不需要由它生成事件。
下一步就是合并到layout中
layout = [
[
sg.Column(file_list_column),
sg.VSeperator(),
sg.Column(image_viewer_column),
]
]
上面代码便是将两个的布局列表以一列一列的形式合并在一起,注意,这里出现了一个新的函数VSeperator()
,VSeperator()
是VerticalSeparator()
的简写,仔细观察的读者可以留意到整个GUI中的中间有一条黑色的直线.
没错,这个代码的功能就是这条黑线。这条黑线是用来分割两个列表布局的,你可以设置一些参数来决定每个布局的比例。
下面就是创建窗体
window = sg.Window("图片查看系统", layout)
最后便是创建一个事件循环,这里分逻辑讲解
while True:
event, values = window.read()
if event == "Exit" or event == sg.WIN_CLOSED:
break
在整个事件中,除了获取事件与对应的值外,你可以通过调用key
来与相应的元素进行对话,这样取出来的值就是你选择得key
与其对应得值字典。
这里用了条件语句来执行什么事件发生,什么事件不发生。
第一个逻辑条件语句如下
if event == "-FOLDER-":
folder = values["-FOLDER-"]
try:
# Get list of files in folder
file_list = os.listdir(folder)
except:
file_list = []
fnames = [
f
for f in file_list
if os.path.isfile(os.path.join(folder, f))
and f.lower().endswith((".png", ".gif"))
]
window["-FILE LIST-"].update(fnames)
如果事件等于-FOLDER-
,即你点击了key
= -FOLDER-
对应的元素,那么接下来就会进行选择文件夹的步骤,这里使用了os.listdir()
来得到文件列表,然后将选择的文件列表里的图片加上".png",或".gif"后缀。同时运用.update()
函数在列表箱子Listbox
里更新所选列表中的所有图片信息。
第二个逻辑代码如下
elif event == "-FILE LIST-": # A file was chosen from the listbox
try:
filename = os.path.join(
values["-FOLDER-"], values["-FILE LIST-"][0]
)
window["-TOUT-"].update(filename)
window["-IMAGE-"].update(filename=filename)
except:
pass
如果事件等于-FILE LIST-
,那么相当于使用者在左边的列表箱子中选择了一个图片文件。选择之后,同样运用.update()
函数更行Image
和Text
元素中的信息。
在两个逻辑中都是用关键字key
来调用相应的元素事件:window[key]
最后就是关闭程序
window.close()
有读者会问,直接按GUI中的离开按钮不香吗? 答案是可以的,但作为程序员,代码是你与计算机交互的工具。
还有一个原因就是在web端的GUI中,如果直接按离开按钮,虽然页面是关闭了,但是这个网页面还是会占据你内存!
简易的计算机视觉系统搭建
作为彩蛋,我们最后讲解一个基于PySimpleGUI
的简易计算机视觉系统搭建
计算机视觉(Computer Vision)是指用计算机实现人的视觉功能——对客观世界的三维场景的感知、识别和理解。而这次的简易计算机视觉系统,将诠释感知与识别。和上节一样,先上代码
import tkinter
import cv2, PySimpleGUI as sg
USE_CAMERA = 0
window, cap = sg.Window('简易的计算机视觉系统', [[sg.Image(filename='', key='image')], ], location=(0, 0), grab_anywhere=True), cv2.VideoCapture(USE_CAMERA)
while window(timeout=20)[0] != sg.WIN_CLOSED:
window['image'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes())
通过上面简单的代码,就能调用电脑摄像头了!小编长得没郭富城帅,这里就不做效果呈现了.......
需要注意的是,你需要将你笔记本的摄像头权限打开,不然会报错!!!下面简单讲解一下上面的代码:
PySimpleGUI
部分的构建在构建图片查看系统中有提及,这里就不细讲。主要是创建一个只有Image
元素的窗体,运行一个逻辑:只有没按关闭按钮就一直循环的事件。这里新增了一个新函数grab_anywhere=True
,是用来启用非阻塞窗口的。
主要讲解一下涉及到的cv2
的一些用法:
cv2.VideoCapture(0)
:打开笔记本的内置摄像头,参数为0。如果参数是视频文件路径,则打开视频
cv2.imencode()
:这个函数将图片格式转换(编码)成流数据,赋值到内存缓存中;主要用于图像数据格式的压缩,方便网络传输。随之相应的就是
cv2.imdecode()
:指从指定的内存缓存中读取数据,并把数据转换(解码)成图像格式;主要用于从网络传输数据中恢复出图像
以上便是本次pySimpleGUI
的进阶版内容讲解,当然我们只是基于图片查看系统的讲解,掌握了方法之后,感兴趣的读者可以自己开发Excel/Word等文档查看系统!
本文的分享就到这里,在下一篇的实战讲解内容中,我们将结合爬虫,更详细的讲解如何做一个带有GUI的爬虫程序!