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

Karen110
• 阅读 1895

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

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

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

  • 图片查看系统的构建

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

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

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

  • PySimpleGUI

  • os

  • cv2

图片查看系统的构建

1、代码与效果呈现

开门见山,先看最终效果和代码,后面再解读,在本节我们需要实现的就是如下图所示的一个图片查看系统,左边输入图片所在文件夹,就可以按顺序查看图片PySimpleGUI 进阶| 原来用Python做一个图片查看系统,还能这么简单!

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

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做一个图片查看系统,还能这么简单!

代码中引入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做一个图片查看系统,还能这么简单!

这里有三个元素:两个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的爬虫程序

**-----**------**-----**---**** 送书 **-----**--------**-----**-****

往期精彩文章推荐:

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

欢迎各位大佬点击链接加入群聊【helloworld开发者社区】:https://jq.qq.com/?_wv=1027&k=mBlk6nzX进群交流IT技术热点。

本文转自 https://mp.weixin.qq.com/s/yalTImTe8F19RfvwS_gvTQ,如有侵权,请联系删除。

点赞
收藏
评论区
推荐文章
blmius blmius
2年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
Jacquelyn38 Jacquelyn38
2年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Stella981 Stella981
2年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Stella981 Stella981
2年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Easter79 Easter79
2年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
3个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这