GUI库PySimpleGUI

1. 简介

图形用户界面(Graphical User Interface,简称 GUI,又称图形用户接口)是指采用图形方式显示的计算机操作用户界面。图形用户界面是一种人与计算机通信的界面显示格式,允许用户使用鼠标等输入设备操纵屏幕上的图标或菜单选项,以选择命令、调用文件、启动程序或执行其它一些日常任务。用户界面通常包括许多视觉元素,如图标、按钮、图形、显示文本和多种输入控件,如复选框、文本输入框等。如何给AI应用程序编写一个图形用户界面?那么就需要选择一个简单好用的GUI开发工具。

Python作为一个容易上手,简单方便的开源编程语言,第三方的开发工具数不胜数,在GUI这个方向同样有很多的工具可以选择。比较常用的GUI开发工具有Tkinter、PyQt、wxPython、Gtk+、Kivy、FLTK和OpenGL等,其中最常用是Tkinter。Tkinter的优点在于是Python内置标准库,无需额外安装,兼容性好,但缺点在于实现效果较为普通,开发体验不好。比较受程序员推崇的是PyQt和wxPython,功能强大,界面优美,相关教程也很多,可惜学习曲线有些陡峭。在比较了多款GUI开发工具之后,我们最终推荐使用PySimpleGUI

PySimpleGUI的优势还在于其内置了多个GUI框架。目前已经集成了tkinter、PyQt、wxPython和 Remi等四种。其中Remi是一个Web界面开发库。如果想要将普通的GUI界面更换为Web界面,只要将前面的导入库“import PySimpleGUI as sg”一句改为“import PySimpleGUIWeb as sg”,其他代码都不需要改变,体现了“一次编写、处处运行”的理念。

本文涉及的部分代码见XEdu帮助文档配套项目集:https://www.openinnolab.org.cn/pjlab/project?id=64f54348e71e656a521b0cb5&sc=645caab8a8efa334b3f0eb24#public

PySimpleGUI

  • 底层框架: 使用的是 Python 的标准 GUI 库 tkinter 作为其底层实现。

  • 目标平台: 桌面环境。通过它,你可以轻松地为 Windows、Mac 和 Linux 创建原生应用程序。

  • 特点:

    • 简单的 API,允许快速构建应用程序。

    • 提供了大量的小部件,如按钮、文本框、列表框等。

    • 可以轻松地与其他 Python 库集成。

官方GitHub仓库地址:https://github.com/PySimpleGUI/PySimpleGUI

PySimpleGUIWeb

  • 底层框架: 使用 Remi 作为其底层实现,它是一个 Python GUI 库,允许你创建的 GUI 在 web 浏览器中运行。

  • 目标平台: Web 浏览器。它旨在为那些想要一个简单的方法来创建 web 应用程序的开发者提供解决方案。

  • 特点:

    • 不需要深入了解 web 开发或 HTML/CSS/JavaScript 的知识。

    • 可以在任何支持的浏览器中运行,无需客户端安装。

    • API 与其他 PySimpleGUI 版本相似,使得从桌面应用迁移到 web 应用变得简单。

官方GitHub仓库地址:https://github.com/PySimpleGUI/PySimpleGUI/tree/master/PySimpleGUIWeb

选择PySimpleGUI还是PySimpleGUIWeb?

在选择使用哪个版本之前,你应该首先确定你的应用程序的需求。如果你需要一个轻量级的桌面应用程序,PySimpleGUI 可能是更好的选择。如果你希望你的应用程序可以在浏览器中运行,那么 PySimpleGUIWeb 更适合。

2. 安装

均可以采用pip命令安装,具体如下:

pip install PySimpleGUI
pip install PySimpleGUIWeb

3.示例代码

以下是一个基本的 PySimpleGUI 示例:

# 导入库
import PySimpleGUI as sg
# 设计窗体布局,用列表来定义每一个元素。
layout = [
    [sg.Text('请输入你的名字:')],
    [sg.Input(key='in')],
    [sg.Button('确认'), sg.Button('取消')],
    [sg.Text('输出:'), sg.Text(key='out')]
]
# 创建窗体
window = sg.Window('PySimpleGUI 范例', layout)
# 监视窗体的事件,并响应。
while True:
    # event为按钮的名称,values为一个字典
    event, values = window.read()
    print(event,values)
    if event in (None, '取消'):
        window['in'].update('')
        window['out'].update('')
    else:
        if values:
            s = '欢迎你,' + values['in']
        window['out'].update(s)
# 关闭窗体
window.close()

上面这段代码一个简单的PySimpleGUI应用程序,它创建了一个包含文本和按钮的窗口。当用户点击”确定”按钮或关闭窗口时,程序将结束。这段代码中最核心的部分在于窗体设计和窗体事件控制部分。其中“window.read()”返回的信息中,event为按钮的名称,values则为一个字典,键名是控件的名称。仔细观察PySimpleGUI代码,会发现和Arduino、掌控板之类开源硬件程序的运行逻辑非常类似——用一个无限循环来处理输入和输出窗体事件。该代码的运行效果如下,界面样式中规中矩,看起来并不丑。

../../_images/pysimplegui.png

4. 借助PySimpleGUI部署简易AI应用

只需准备好模型后,使用PySimpleGUI创建一个带GUI的简单AI应用。考虑到计算机视觉(CV)方向的模型都需要结合摄像头,界面中得显示实时画面,那就需要借助Image类型的对象,然后在窗体事件控制部分中实时更新画面。

示例1:带窗体的摄像头实时推理的程序(图像分类)

下面是一段使用PySimpleGUIWeb与OpenCV来显示实时的摄像头图像并对其进行实时推理。在推理过程中,使用的是ONNX模型,推理的代码是借助XEdu团队推出的模型部署工具BaseDeploy,代码较为简洁。关于基于MMEdu训练的模型转换为ONNX的说明可见最后一步:AI模型转换与部署

# 带窗体的摄像头程序,自动推理
# 模型为1000分类预训练模型(MobielNet)
import PySimpleGUIWeb as sg
from XEdu.hub import Workflow as wf
import cv2

model = wf(task='cls_imagenet')

def my_inf(frame):
    result1 = model.inference(frame)
    result2 = model.format_output()
    return result2

#背景色
sg.theme('LightGreen')
#定义窗口布局
layout = [
  [sg.Image(filename='', key='image',size=(600, 400))],
  [sg.Button('关闭', size=(20, 1))],
  [sg.Text('推理结果:',key='res')]
]

#窗口设计
window = sg.Window('OpenCV实时图像处理',layout,size=(600, 500))
#打开内置摄像头
cap = cv2.VideoCapture(1)
while True:
    event, values = window.read(timeout=0, timeout_key='timeout')
    #实时读取图像,重设画面大小
    ret, frame = cap.read()
    imgSrc = cv2.resize(frame, (600,400))
    res = my_inf(frame) 
    if res:
        print('推理结果为:',res)
        window['res'].update('推理结果:'+res['预测类别'])

    #画面实时更新
    imgbytes = cv2.imencode('.png', imgSrc)[1].tobytes()
    window['image'].update(data=imgbytes)
    if event in (None, '关闭'):
        break
# 退出窗体
cap.release()
window.close()

示例2:带窗体的摄像头实时推理的程序(目标检测)

一般来说,目标检测的代码会在推理画面上显示检测出来的目标,并且绘制一个矩形。因而,BaseDeploy的推理函数会返回识别后的画面。

# 带窗体的摄像头程序,自动推理
# 模型为80类目标检测预训练模型(SSD_Lite)
import PySimpleGUIWeb as sg
from XEdu.hub import Workflow as wf
import cv2

model = wf(task='mmedu',checkpoint='det.onnx')

def my_inf(frame):
    global model
    res1, img = model.inference(frame,img_type='cv2')
    # 转换推理结果
    res2 = model.format_output()
    if len(res2) == 0:
        return None,None
    classes = []
    print(res2)
    # 提取预测结果
    for res in res2:
        classes.append(res['预测值'])
    return str(classes),img

#背景色
sg.theme('LightGreen')
#定义窗口布局
layout = [
  [sg.Image(filename='', key='image',size=(600, 400))],
  [sg.Button('关闭', size=(20, 1))],
  [sg.Text('推理结果:',key='res')]
]

# 建立窗体
window = sg.Window('OpenCV实时图像处理',layout,size=(600, 500))
#打开摄像头
cap = cv2.VideoCapture(0)
while True:
    event, values = window.read(timeout=0, timeout_key='timeout')
    if event in (None, '关闭'):
        break
    # 实时读取图像
    ret, frame = cap.read()
    res, img = my_inf(frame)
    if res:
        window['res'].update('推理结果:'+res)
        newimg = img
    else:
        newimg = frame
    # 实时更新画面
    newimg = cv2.resize(newimg, (600,400))
    imgbytes = cv2.imencode('.png', newimg)[1].tobytes()
    window['image'].update(data=imgbytes)
# 退出窗体
cap.release()
window.close()