解释春风无限恨,沉香亭北倚栏杆。 

大家好,在昨天的文章中我们已经介绍了为什么以及如何基本使用PySimpleGUI,并且对一些比较常用的元素(element)也有所了解。

本文将对基础版中的一些元素与新讲解的元素进行组合,构建一个图片查看系统与一个简易的计算机视觉系统(代码调用前置照相机)

作为PySimpleGUI的进阶篇,我将分为以下两个部分讲解:

  • 图片查看系统的构建
  • 简易计算机视觉系统(cv)的构建

PySimpleGUI 进阶| 原来用Python做一个图片查看系统,还能这么简单!_人工智能

本次内容主要涉及的Python模块:

  • PySimpleGUI
  • os
  • cv2

  图片查看系统的构建

1、代码与效果呈现

开门见山,先看最终效果和代码,后面再解读,在本节我们需要实现的就是如下图所示的一个图片查看系统,左边输入图片所在文件夹,就可以按顺序查看图片

PySimpleGUI 进阶| 原来用Python做一个图片查看系统,还能这么简单!_javascript_02

下面为全部的源码,可以看到并不是很多,这也体现了我们之前说的简单性

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中的第一个列表元素,是如下图的代码


PySimpleGUI 进阶| 原来用Python做一个图片查看系统,还能这么简单!_编程语言_03

代码中引入os模块对文件夹进行调用,在创建一个垂直方向的元素嵌套列表file_list_column,里面的元素如上图般放置。在嵌套列表里有4个元素:

  • Text
  • InputText
  • FolderBrowse
  • Listbox

其中代码中的In等价于InputText,在上节中有提及。总体来说,上述元素的功能就是打开图片所在文件夹和陈列所有图片信息。

Text中写的"Image Folder"是一个标识,用来说明。

InputText中先设置了框的大小是长25,宽1的单位长度。

enable_eventskey两个参数是一起用的。这里的参数key是GUI中非常重要的参数,是用来在整个GUI中鉴别特殊的元素的。比如此处中,定义了一个"-FOLDER-"的身份给-

InputText这个元素。有了这个key,你可以在循环事件中去调用它。学习过其他GUI库,诸如wxpythonTkinter等,这个key就像是用来绑定事件的函数一样。在面向对象语言中,这就像定义了一个类一般。但这些都是非常复杂的,而做的像key这样的,足可以说明PySimpleGUI的便利。单独来讲,key是用来标记的,enable_events就是用来控制元素对应事件循环中开始与结束,相当于执行元素中的事件。

最后一个元素是Listbox,显而易见,这是用来展示所选文件列表中的所有照片路径的信息。你可以在这个列表中点击你想看的照片。对于这个列表箱子,你可以传递字符串列表来填充他。

Listbox是一个列表箱子,顾名思义是一个列表类型的。

Listbox里面先设置了空的列表值,这是因为第一次打开图形交互页面时,由于你没有选择文件夹,所以对应的箱子是空的。和上面一样设置的keyenable_events标记了key为"-FILE LIST-"与开启绑定事件功能,并且设置了(40,20)的大小。

接下里看layout中的第二个列表元素

image_viewer_column = [
    [sg.Text("从左边图片列表中选择一张图片:")],
    [sg.Text(size=(40, 1), key="-TOUT-")],
    [sg.Image(key="-IMAGE-")],
]

这是如图的代码:

PySimpleGUI 进阶| 原来用Python做一个图片查看系统,还能这么简单!_css_04

这里有三个元素:两个TextImage

第一个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()函数更行ImageText元素中的信息。

在两个逻辑中都是用关键字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的爬虫程序