PySimpleGUI - 快速指南


PySimpleGUI - 简介

面向人类的 Python GUI

PySimpleGui项目最初是作为 TKinter 包的包装器开始的,包与 Python 的标准库捆绑在一起,其目标是简化 GUI 构建过程。

PySimpleGui 随后添加了基于 PySide 库(它本身将最初用 C++ 编写的 Qt GUI 工具包移植到 Python)和 WxPython(它移植了另一个流行的 GUI 工具包,称为 WxWidgets)设计桌面 GUI 的功能。这些库分别称为PySimpleGUIQtPySimpleGUIWx

PySimpleGui 系列的最新成员是PySimpleGUIWeb包,它使用 Remi(REMote 接口库)来构建在网页中呈现的 GUI 设计。

PySimpleGui 组中的所有包都遵循相似的 API,这意味着 GUI 元素的名称、它们的属性和方法在所有四个包中都是相同的。这样一来,只需替换 import 语句(其余代码不变),就可以得到相应的 GUI 设计渲染。这实际上是 PySimpleGui 最重要的特性。这就是为什么它被称为“人类的 Python GUI”。

与其他 GUI 框架的比较

Python 程序员有多种 GUI 框架可供选择来开发 GUI 应用程序。TKinter 是正式包含在Python 标准库中的一个。其他的,其中大多数是开源的,必须明确安装。

先生。 库和描述
1 TkInter

包含在Python标准库中

2 pyqt

Qt 应用程序框架的 Python 3 绑定。

3 派赛德

Qt for Python(以前称为 PySide)为 Qt 跨平台应用程序和 UI 框架提供官方 Python 绑定。

4 PySimpleGUI

将 tkinter、Qt (pyside2)、wxPython 和 Remi(用于浏览器支持)封装在非 OOP API 中

5 wxPython

支持 Windows/Unix/Mac。支持 Python 2.7 和 >=3.4。包装并扩展 wxWidgets 工具链。

6 PyG对象

PyGObject 是一个 Python 包,它为基于 GObject 的库提供绑定,例如 PyGtk 的 GTK Replacement。

7 PyForms

用于开发 GUI 应用程序的 Python 框架,可轻松促进模块化软件设计和代码可重用性。

PySimpleGUI - 环境设置

PySimpleGui 支持 Python 3.x 版本以及 Python 2.7 版本。主要端口 PySimpleGui 没有任何外部依赖项,因为它所基于的 Tkinter 是 Python 标准库的一部分,因此不需要单独安装。通过pip安装程序在当前Python3环境中安装,如下

pip3 install PySimpleGUI

要验证库是否已正确安装,请输入以下语句 -

>>> import PySimpleGUI
>>> PySimpleGUI.version
'4.60.1 Released 22-May-2022'

如果 PIP 安装不起作用,您可以从 Github 存储库(https://github.com/PySimpleGUI/PySimpleGUI)下载“pysimplegui.py” ,并将其与导入它的应用程序一起放入您的文件夹中。

pysimplegui.py文件具有“main()”函数。当从 Python 提示符调用时,它会生成以下窗口以确认该包已正确安装。

>>> import PySimpleGUI as psg
>>> psg.main()
Starting up PySimpleGUI Diagnostic & Help System
PySimpleGUI long version = 4.60.1 Released 22-May-2022
PySimpleGUI Version 4.60.1
tcl ver = 8.6 tkinter version = 8.6
Python Version 3.6.8 (tags/v3.6.8:3c6b436a57, Dec 24 2018,
00:16:47) [MSC v.1916 64 bit (AMD64)]
tcl detailed version = 8.6.6
PySimpleGUI.py location F:\python36\lib\sitepackages\PySimpleGUI\PySimpleGUI.py

GUI 窗口如下所示:

环境设置

如果您使用的Python3版本早于3.4,您可能需要安装“typing”模块,因为它没有包含在相应的标准库中

pip3 install typing

对于 Python 2.7,将名称更改为 PySimpleGUI27。

pip3 install PySimpleGUI27

您可能还需要安装 2.7 版本的“future”

pip3 install future

但是,需要注意的是,Python 软件基金会并不正式支持 Python 2.x 分支。

PySimpleGUI - 你好世界

使用 PySimpleGUI 的第一个窗口

要检查 PySimpleGUI 及其依赖项是否已正确安装,请使用任何支持 Python 的编辑器输入以下代码并将其另存为“hello.py”。

import PySimpleGUI as psg
layout = [[psg.Text(text='Hello World',
   font=('Arial Bold', 20),
   size=20,
   expand_x=True,
   justification='center')],
]
window = psg.Window('HelloWorld', layout, size=(715,250))
while True:
   event, values = window.read()
   print(event, values)
   if event in (None, 'Exit'):
      break
window.close()

上面的代码构造了一个带有 Text 元素(相当于 TKinter 中的 Label)的窗口,并显示位于窗口宽度中央的“Hello World”消息。

从命令终端运行该程序:

Python hello.py

程序生成的输出应类似于下面显示的输出-

第一个窗口

等效的 Tkinter 代码

要使用纯 Tkinter 代码获得类似的输出,我们需要以下 Python 脚本 -

from tkinter import *
window=Tk()
lbl=Label(window, text="Hello World",
   fg='white', bg='#64778D',
   font=("Arial Bold", 20))
lbl.place(x=300, y=15)
window.title('HelloWorld Tk')
window['bg']='#64778D'
window.geometry("715x250+10+10")
window.mainloop()

所有其他功能保持不变,除了我们使用waitress模块的serve()函数来启动 WSGI 服务器。运行程序后在浏览器中访问“/”路由时,Hello World 消息将像以前一样显示。

除了函数之外,可调用类也可以用作视图。可调用类是重写__call__()方法的类。

from pyramid.response import Response
class MyView(object):
   def __init__(self, request):
      self.request = request
   def __call__(self):
      return Response('hello world')

PySimpleGUIQt

PySimpleGUI API 的对象模型已与 PySide2 包(Qt 图形工具包的 Python 端口)中定义的小部件兼容。PySimpleGui 的 Qt 版本称为 PySimpleGUIQt。可以使用以下 PIP 命令类似地安装它 -

pip3 install PySimpleGUIQt

由于该软件包依赖于 PySide2,因此也会安装相同的软件包。

>>> import PySide2
>>> PySide2.__version__
'5.15.2.1'
>>> import PySimpleGUIQt
>>> PySimpleGUIQt.version
'0.35.0 Released 6-Jun-2020'

如前所述,PySimpleGui 项目最重要的特征是为一个包编写的代码与另一个包完全兼容。因此,之前使用的 hello.py 程序可以直接用于 Qt 版本。唯一需要的更改是导入 PySimpleGUIQt 而不是 PySimpleGui。

import PySimpleGUIQt as psg
layout = [[psg.Text(text='Hello World',
   font=('Arial Bold', 20),
   justification='center')],
]
window = psg.Window('HelloWorldQt', layout, size=(715,250))
while True:
   event, values = window.read()
   print(event, values)
   if event in (None, 'Exit'):
      break
window.close()

输出非常相似

GUIQT

等效的 PySide2 代码

达到相同结果的纯 PySide2 代码如下 -

import sys
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *
def window():
   app = QApplication(sys.argv)
   w = QWidget()
   w.setStyleSheet("background-color: #64778D;")

   b = QLabel(w)
   b.setText("Hello World!")
   b.setFont(QFont('Arial Bold', 20))
   b.setAlignment(Qt.AlignCenter)
   b.setStyleSheet("color: white;")
   b.setGeometry(100, 100, 715, 250)
   b.move(50, 20)

   w.setWindowTitle("HelloWorldQt")
   w.show()
   sys.exit(app.exec_())
   if __name__ == '__main__':
      window()

它将产生相同的输出窗口。

PySimpleGUIWx

该模块封装了 WxPython 工具包中定义的 GUI 小部件的功能。WxPython 是广泛使用的 WxWidgets 库的 Python 端口,最初是用 C++ 编写的。显然,PySimpleGUIWx 依赖于 WxPython 包,因此后者将通过以下 PIP 命令自动安装 -

pip3 install PySimpleGUIWx

要确认 PySimpleGUIWx 和 WxPython 均已正确安装,请在 Python 终端中输入以下语句。

>>> import PySimpleGUIWx
>>> PySimpleGUIWx.version
'0.17.1 Released 7-Jun-2020'
>>> import wx
>>> wx.__version__
'4.0.7'

“hello.py”脚本中不需要进行太多更改。我们只需在“导入”语句中将 PySimpleGUI 替换为 PySimpleGUIWx 模块即可。

import PySimpleGUIWx as psg
layout = [[psg.Text(text='Hello World',
   font=('Arial Bold', 20),
   size=(500, 5),
   justification='center')],
]
window = psg.Window('HelloWorldWx', layout, size=(715, 250))
while True:
   event, values = window.read()
   print(event, values)
   if event in (None, 'Exit'):
      break
window.close()

它将产生以下输出

图形用户界面

请注意,您需要更复杂的代码才能使用纯 WxPython 代码获得类似的输出,如下所示 -

import wx
app = wx.App()
window = wx.Frame(None, title="WxPython", size=(715, 250))
panel = wx.Panel(window)
panel.SetBackgroundColour((100, 119, 141))
label = wx.StaticText(panel, -1, style=wx.ALIGN_CENTER)
label.SetLabel("Hello World")
label.SetForegroundColour((255, 255, 255))
font = wx.Font()
font.SetFaceName("Arial Bold")
font.SetPointSize(30)
label.SetFont(font)
window.Show(True)
app.MainLoop()

它将显示一个顶级窗口,其中包含一个标题为“Hello World”的文本标签。

PySimpleGUIWeb

Remi(REMote Interface)是一个用于在 Web 浏览器中呈现的 Python 应用程序的 GUI 库。PySimpleGUIWeb 包将原始 PySimpleGui 库移植到 Remi,以便其应用程序可以在浏览器中运行。以下 PIP 命令将在当前 Python 环境中安装 PySimpleGUIWeb 和 Remi -

pip3 install PySimpleGUIWeb

在编写应用程序之前检查它们的安装是否正确。

>>> import PySimpleGUIWeb
>>> PySimpleGUIWeb.version
'0.39.0 Released 6-Jun-2020'

以下脚本是原始 Hello World 程序的 PySimpleGUIWeb 版本。

import PySimpleGUIWeb as psg
layout = [[psg.Text(text='Hello World',
   font=('Arial Bold', 20),
   justification='center')]]
window = psg.Window('HelloWorldWeb', layout)
while True:
   event, values = window.read()
   print(event, values)
   if event in (None, 'Exit'):
      break
window.close()

使用纯 Remi 库的功能获得类似的输出有点复杂,如以下代码所示:

import remi.gui as gui
from remi import start, App
class HelloWeb(App):
   def __init__(self, *args):
      super(HelloWeb, self).__init__(*args)
   def main(self):
      wid = gui.VBox(style={"background-color": "#64778D"})
      self.lbl = gui.Label('Hello World', width='100%', height='100%',
      style={ "color":"white",
         "text-align": "center",
         "font-family": "Arial Bold",
         "font-size": "20px"}
      )
      wid.append(self.lbl)
      return wid
      if __name__ == "__main__":
         start(HelloWeb, debug=True, address='0.0.0.0', port=0)

当我们运行这些程序时,Remi 服务器启动,浏览器窗口自动打开并显示 Hello World 消息。

图形用户界面网页

这里我们看到了用 PySimpleGUI、PySimpleGUIQt、PySimpleGUIWx 和 PySimpleGUIWeb 库编写的 Hello World 程序。我们可以看到小部件库保持不变。此外,相同的 Hello world 程序,当分别用纯 Tkinter、PySide、WxPython 和 Remi 编写时,会变得比 PySimpleGUI 版本更加复杂和乏味。

PySimpleGUI - 弹出窗口

PySimpleGUI 模块中以前缀 popup* 开头的函数生成预定义外观的窗口。弹出功能的名称表明其上存在的按钮的用途和配置。这些弹出窗口只需一行代码即可创建。每个弹出窗口都有特定的目的,然后立即关闭。

最基本的弹出窗口是由popup()函数创建的。它可以像 print() 函数一样使用,在窗口上显示多个参数,以及一个“确定”按钮。它的作用就像一个消息框,按下“确定”按钮后立即消失

>>> import PySimpleGUI as psg
>>> psg.popup("Hello World")

它会显示一个弹出窗口,其中包含“Hello World”文本和“确定”按钮。请注意,可以显示多个字符串。以下具有不同按钮配置的弹出窗口可用 -

  • popup_ok - 仅显示带有“确定”按钮的弹出窗口

  • popup_ok_cancel - 显示带有“确定”和“取消”按钮的弹出窗口

  • popup_cancel - 显示带有“已取消”按钮文本的弹出窗口

  • popup_yes_no - 显示带有“是”和“否”按钮的弹出窗口

  • popup_error - 带有彩色按钮和“错误”作为按钮文本的弹出窗口

这些函数返回用户按下的按钮的文本。例如,如果用户按下 ok-cancel 弹出窗口的 OK 按钮,则会返回 Ok,可用于进一步的编程逻辑。

以下弹出窗口接受用户以文本形式的输入,或让用户从选择器中选择文件/文件夹/日期。

  • popup_get_text - 显示带有文本输入字段的弹出窗口。返回输入的文本,如果关闭/取消则返回 None

  • popup_get_file - 显示带有文本输入字段和浏览按钮的弹出窗口,以便用户可以选择文件。

  • popup_get_folder - 显示带有文本输入字段和浏览按钮的弹出窗口,以便可以选择文件夹。

  • popup_get_date - 显示日历窗口,获取用户的选择,以元组形式返回(周一、日、年)

当用户做出选择并按下“确定”按钮时,弹出窗口的返回值是文本,可以在程序中进一步使用。

以下脚本显示了上述一些弹出窗口的使用 -

import PySimpleGUI as psg
text = psg.popup_get_text('Enter your name', title="Textbox")
print ("You entered: ", text)
file=psg.popup_get_file('Select a file',  title="File selector")
print ("File selected", file)
folder=psg.popup_get_folder('Get folder', title="Folder selector")
print ("Folder selected",folder)
ch = psg.popup_yes_no("Do you want to Continue?",  title="YesNo")
print ("You clicked", ch)
ch = psg.popup_ok_cancel("Press Ok to proceed", "Press cancel to stop",  title="OkCancel")
if ch=="OK":
   print ("You pressed OK")
if ch=="Cancel":
   print ("You pressed Cancel")
psg.popup_no_buttons('You pressed', ch, non_blocking=True)
psg.popup_auto_close('This window will Autoclose')

输出- 上述代码生成的弹出窗口如下所示 -

弹出窗口

以下输出显示在 Python控制台上-

You entered: Tutorialspoint
File selected F:/python36/hello.png
Folder selected F:/python36/Scripts
You clicked Yes
You pressed Cancel

所有类型的弹出窗口都是继承自弹出窗口类的各个类的对象。它们都具有一组共同的属性。这些属性具有一定的默认值,可用于自定义弹出对象的外观和Behave。下表列出了常用参数 -

类型 范围 描述
任何 *参数 要在弹出窗口中显示的值
斯特 标题 窗口的可选标题。
(str, str) 或无 按钮颜色 显示按钮的颜色(文本颜色、按钮颜色)
斯特 背景颜色 窗口的背景颜色
斯特 文字颜色 文字颜色
布尔 自动关闭 如果为 True 窗口将自动关闭
INT 自动关闭持续时间 自动关闭窗口之前保持窗口打开的时间(以秒为单位)
布尔 非阻塞 如果为 True,则将立即从函数返回,而不等待用户的输入。
元组[字体名称、大小、修饰符] 字体 指定字体系列、大小等。元组或单字符串格式“名称大小样式”。
布尔 随处抓取 如果 True 可以抓取任意位置来移动窗口。
(整数,整数) 地点 屏幕上显示窗口左上角的位置。默认窗口位于屏幕中央
布尔 保持在最前 如果为 True,窗口将保持在所有当前窗口之上
布尔 莫代尔 如果为 True,则使弹出窗口的Behave类似于模态窗口。默认=真

滚动弹出窗口

popup_scrolled ()函数生成一个弹出窗口,其中有一个可滚动文本框。使用它来显示大量文本,由许多行组成,字符数超过宽度。

size 属性是一个元组 (w, h),其中“w”是一行中的字符数,“h”是一次显示的行数。如果文本的字符数/行数超过“w”或“h”,文本框的水平/垂直滚动条将变为活动状态。

在以下示例中,一个大文件 zen.txt 显示在带有可滚动文本框的弹出窗口中。该文件包含被称为“Python Zen”的 Python 设计原则。

import PySimpleGUI as psg
file=open("zen.txt")
text=file.read()
psg.popup_scrolled(text, title="Scrolled Popup", font=("Arial Bold", 16), size=(50,10))

它将产生以下输出-

滚动弹出窗口

进度表

“one_line_progress_meter”是一个弹出窗口,显示正在进行的长流程(例如循环)的可视化表示。它显示某个参数的瞬时值、完成该过程的估计时间以及经过的时间。

在以下示例中,逐字符读取文本文件。进度表以进度条的形式显示进程的进度、完成所需的预计时间以及计数的瞬时值。

import PySimpleGUI as psg
import os
size = os.path.getsize('zen.txt')
file=open("zen.txt")
i=0
while True:
   text=file.read(1)
   i=i+1
   if text=="":
      file.close()
      break
   print (text,end='')
   psg.one_line_progress_meter(
      'Progress Meter', i, size,
      'Character Counter'
   )

它将产生以下输出窗口 -

进度表

调试弹出窗口

在程序执行期间,通常需要跟踪某些变量的中间值,尽管在以下输出中不需要。这可以通过 PySimpleGUI 库中的Print()函数来实现。

注意- 与 Python 的内置print()函数不同,该函数具有大写的“P”)。

当程序第一次遇到此函数时,会出现调试窗口,并且所有后续打印都会在其中回显。另外,我们可以使用EasyPrinteprint也有同样的效果。

以下程序计算用户输入的数字的阶乘值。在 for 循环内,我们希望跟踪每次迭代中的 f(阶乘)值。这是由打印功能完成并显示在调试窗口中。

import PySimpleGUI as psg
f=1
num=int(psg.popup_get_text("enter a number: "))
for x in range(1, num+1):
   f=f*x
   psg.Print (f,x)
print ("factorial of {} = {}".format(x,f))

假设用户输入 5,调试窗口将显示以下输出-

调试窗口

PySimpleGUI - 窗口类

弹出窗口具有按钮、文本标签和文本输入字段的预定义配置。Window 类允许您设计更灵活的 GUI。除了这些元素之外,还可以使用其他元素,例如列表框、复选框、单选按钮等。您还可以向 GUI 提供菜单系统。某些专门的小部件(例如微调器、滑块等)也可以用于使设计更加有效。

窗口可以是非持久窗口,类似于弹出窗口。它会阻止程序流,直到用户通过单击客户端区域上的按钮或标题栏中的关闭 (X) 按钮将其关闭。

另一方面,持久窗口继续可见,直到发生导致其关闭的事件。异步窗口是一种内容定期更新的窗口。

布局结构

窗口客户区中元素或小部件的放置由列表对象列表控制。每个列表元素对应于窗口表面上的一行,并且可能包含 PySimpleGUI 库中可用的一个或多个 GUI 元素。

第一步是通过绘制如下图来可视化元素的放置 -

布局

窗口上的元素放置在四行中。前三行有一个 Text 元素(显示静态文本)和一个 InputText 元素(用户可以在其中输入)。最后一行有两个按钮,确定和取消。

这在列表列表中表示如下 -

import PySimpleGUI as psg
layout = [
   [psg.Text('Name '),psg.Input()],
   [psg.Text('Address '), psg.Input()],
   [psg.Text('Email ID '), psg.Input()],
   [psg.OK(), psg.Cancel()]
]

该列表对象用作 Window 类的构造函数的布局参数值。

window = psg.Window('Form', layout)

这将显示所需的窗口。用户输入存储在名为值的字典中。当用户按下“确定”按钮时,将调用 Window 类的 read() 方法,窗口立即关闭

渲染窗口的完整代码如下 -

import PySimpleGUI as psg
psg.set_options(font=('Arial Bold', 16))
layout = [
   [psg.Text('Name ', size=(15,1)),psg.Input(expand_x=True)],
   [psg.Text('Address ', size=(15,1)), psg.Input(expand_x=True)],
   [psg.Text('Email ID ', size=(15,1)), psg.Input(expand_x=True)],
   [psg.OK(), psg.Cancel()]
]
window = psg.Window('Form', layout, size=(715,207))
event, values = window.read()
print (event, values)
window.close()

这是显示的输出-

布局结构

输入如图所示的数据,然后按“确定”按钮。这些值将打印如下 -

OK {0: 'Kiran Gupta', 1: 'Mumbai', 2: 'kiran@gmail.com'}

如果填写数据后按“取消”按钮,打印的结果将是 -

Cancel {0: 'Kiran Gupta', 1: 'Mumbai', 2: 'kiran@gmail.com'}

持久窗口

请注意,一旦单击任何按钮(或标题栏中的“X”按钮),该窗口就会关闭。为了使窗口保持活动状态,直到按下称为 Exit 的特殊类型按钮,或者按“X”关闭窗口,read() 方法被置于无限循环中,并在 WIN_CLOSED 事件发生时(当 Exit 按钮时)中断。被按下)或退出事件发生(当按下“X”按钮时)。

让我们将上面代码中的“取消”按钮更改为“退出”按钮。

import PySimpleGUI as psg
layout = [
   [psg.Text('Name '), psg.Input()],
   [psg.Text('Address '), psg.Input()],
   [psg.Text('Email ID '), psg.Input()],
   [psg.OK(), psg.Exit()]
]
window = psg.Window('Form', layout)
while True:
   event, values = window.read()
   if event == psg.WIN_CLOSED or event == 'Exit':
      break
   print (event, values)
window.close()

窗口的外观将与以前类似,只是它不再是“取消”,而是具有“退出”按钮。

持久窗口

输入的数据将以元组的形式打印。第一个元素是事件,即按钮的标题,第二个元素是一个字典,其键是递增数字,值是输入的文本。

OK {0: 'kiran', 1: 'Mumbai', 2: 'kiran@gmail.com'}
OK {0: 'kirti', 1: 'Hyderabad', 2: 'kirti@gmail.com'}
OK {0: 'karim', 1: 'Chennai', 2: 'karim@gmail.com'}

窗口方法

Window 类中定义的重要方法是read()方法,用于收集所有输入元素中输入的值。Window 类还有其他方法来自定义外观和Behave。它们列在下面 -

先生。 方法及说明
1 添加行

将单行元素添加到窗口的“self.Rows”变量

2 添加行

循环遍历元素列表的列表,并将每一行、列表添加到布局中。

3 关闭

关闭窗口以便正确释放资源。

4 禁用

禁止窗口接受用户的任何输入

5 消失

导致窗口从屏幕上“消失”,但保留在任务栏上。

6 使能够

重新启用窗口以接受用户输入

7 充满

使用作为字典提供的数据填充作为输入字段的元素。

8 查找元素

查找与提供的键关联的元素对象。相当于“element = window[key]”

9 获取屏幕尺寸

获取屏幕尺寸。

10 隐藏

从屏幕和任务栏隐藏窗口

11 从磁盘加载

从“SaveToDisk”函数创建的 Pickle 文件中恢复值

12 布局

用小部件列表的列表填充窗口。

13

从您的窗口获取所有数据。传入等待超时(以毫秒为单位)。

14 再现

使消失的窗口再次显示。

15 保存到磁盘

将每个输入元素中包含的值保存到 pickle 文件中。

16 设置标题

更改任务栏中窗口的标题

使用密钥更新窗口

用户在窗口布局上的不同输入元素中输入的数据以字典格式存储。字典键按照从左到右、从上到下的顺序对应于输入元素进行编号(从0开始)。我们可以通过字典运算符来引用输入数据。这意味着第一个元素中的数据由“values[0]”返回。

values = {0: 'kiran', 1: 'Mumbai', 2: 'kiran@gmail.com'}
data = [values[k] for k in values.keys()]
print (data)

它将在控制台上打印以下内容 -

['kiran', 'Mumbai', 'kiran@gmail.com']

但是,如果要以编程方式操作元素的值,则必须通过为其键参数分配唯一的字符串值来初始化该元素。元素的键就像变量或标识符的名称,这使得以编程方式处理读取或为其赋值变得方便。

关键参数应该是一个字符串。约定是它应该是一个大写字符串,前面和后面都有一个“-”字符(示例:“- NAME-”)。但是,可以使用任何字符串。

让我们将键分配给上面示例中的输入元素,如下所示 -

layout = [
   [psg.Text('Name '),psg.Input(key='-NM-')],
   [psg.Text('Address '), psg.Input(key='-AD-')],
   [psg.Text('Email ID '), psg.Input(key='-ID-')],
   [psg.OK(), psg.Exit()],
]

因此,在read()方法之后返回的值字典将包含键标识符,而不是之前的整数。

OK {'-NM-': 'Kiran', '-AD-': 'Mumbai', '-ID-': 'kiran@gmail.com'}

现在,values[-NM-'] 将获取“Kiran”。该键可以分配给任何元素,而不仅仅是输入元素。您可以使用相同的键对元素调用 Update。我们可以使用Window对象的“find_element(key)”,或者使用window['key']来引用元素。

让我们扩展前面的示例,在“确定”和“取消”按钮之前添加一行,并使用“-OUT-”键添加一个空文本元素。在 OK 事件中,此文本标签显示在具有键“-NM-”、“-AD-”和“-ID-”的三个输入元素中输入的数据的串联

import PySimpleGUI as psg
psg.set_options(font=('Arial Bold', 16))
layout = [
   [psg.Text('Name ', size=(15, 1)),
   psg.Input(key='-NM-', expand_x=True)],
   [psg.Text('Address ', size=(15, 1)),
   psg.Input(key='-AD-', expand_x=True)],
   [psg.Text('Email ID ', size=(15, 1)),
   psg.Input(key='-ID-', expand_x=True)],
   [psg.Text('You Entered '), psg.Text(key='-OUT-')],
   [psg.OK(), psg.Exit()],
]
window = psg.Window('Form', layout, size=(715, 200))
while True:
   event, values = window.read()
   print(event, values)
   out = values['-NM-'] + ' ' + values['-AD-'] + ' ' + values['-ID-']
   window['-OUT-'].update(out)
   if event == psg.WIN_CLOSED or event == 'Exit':
      break
window.close()

运行上面的代码,在三个输入元素中输入文本,然后按“确定”。-OUT- 文本标签将更新,如下所示 -

更新窗口

下面给出了使用 key 属性的另一个示例。输入元素被分配关键参数 -FIRST- 和 -SECOND-。有两个标题为“添加”和“子”的按钮。文本元素根据按下的按钮显示两个数字的加法或减法。

import PySimpleGUI as psg
import PySimpleGUI as psg
psg.set_options(font=('Arial Bold', 16))
layout = [
   [psg.Text('Enter a num: '), psg.Input(key='-FIRST-')],
   [psg.Text('Enter a num: '), psg.Input(key='-SECOND-')],
   [psg.Text('Result : '), psg.Text(key='-OUT-')],
   [psg.Button("Add"), psg.Button("Sub"), psg.Exit()],
]
window = psg.Window('Calculator', layout, size=(715, 180))
while True:
   event, values = window.read()
   print(event, values)
   if event == "Add":
      result = int(values['-FIRST-']) + int(values['-SECOND-'])
   if event == "Sub":
      result = int(values['-FIRST-']) - int(values['-SECOND-'])
   window['-OUT-'].update(result)
   if event == psg.WIN_CLOSED or event == 'Exit':
      break
window.close()

以下屏幕截图显示了按下“添加”按钮时的结果。

更新窗口

无边框窗

默认情况下,应用程序窗口在客户区域上方创建一个标题栏,其中所有其他元素都放置在布局中。标题栏由左侧的窗口标题和右侧的控制按钮(最小化、恢复/最大化和关闭)组成。然而,特别是对于类似信息亭的应用程序,不需要标题栏。您可以通过将 Window 对象的“no_titlebar”属性设置为“True”来删除标题栏。

边框窗口

要终止此类应用程序,必须在发生“退出”按钮事件时终止事件循环。

禁用关闭的窗口

如果您希望阻止用户最小化应用程序窗口,则应将 Window 对象的“disable_minimize”属性设置为 True。同样,“disable_close”属性的 True 值会显示关闭按钮,但不会创建 WINDOW_CLOSED 事件。

边框已禁用

透明窗

Window对象的“alpha_channel”属性决定了窗口的透明度。它的值在 0 到 1 之间。默认情况下,它是 0,这意味着窗口显示为不透明。将其设置为 1 使其完全透明。0 到 1 之间的任何浮点值都会使透明度成比例。

透明窗

多个窗口

PySimpleGUI 允许同时显示多个窗口。PySimpleGUI 模块中的静态函数在调用时读取所有活动窗口。要使窗口处于活动状态,必须对其进行最终确定。该函数返回一个(窗口、事件、值)结构的元组。

window, event, values = PySimpleGUI.read_all_windows()

如果没有窗口打开,则其返回值为(None, WIN_CLOSED, None)

在下面的代码中,两个函数“win1()”和“win2()”在调用时分别创建一个窗口。从第一个窗口开始,标题为“Window-2”的按钮会打开另一个窗口,因此两个窗口都处于活动状态。当第一个窗口发生 CLOSED 事件时,两个窗口都关闭并且程序结束。如果按下第二个窗口上的“X”按钮,它将被标记为关闭,而第一个窗口保持打开状态。

import PySimpleGUI as psg
def win1():
   layout = [
      [psg.Text('This is the FIRST WINDOW'), psg.Text('', key='-OUTPUT-')],
      [psg.Text('popup one')],
      [psg.Button('Window-2'), psg.Button('Popup'), psg.Button('Exit')]
   ]
   return psg.Window('Window Title', layout, finalize=True)
   def win2():
      layout = [
         [psg.Text('The second window')],
         [psg.Input(key='-IN-', enable_events=True)],
         [psg.Text(size=(25, 1), key='-OUTPUT-')],
         [psg.Button('Erase'), psg.popup('Popup two'), psg.Button('Exit')]]
         return psg.Window('Second Window', layout, finalize=True)
window1 = win1()
window2 = None
while True:
   window, event, values = psg.read_all_windows()
   print(window.Title, event, values)
   if event == psg.WIN_CLOSED or event == 'Exit':
      window.close()
   if window == window2:
      window2 = None
   elif window == window1:
      break
   elif event == 'Popup':
      psg.popup('Hello Popup')
   elif event == 'Window-2' and not window2:
      window2 = win2()
   elif event == '-IN-':
      window['-OUTPUT-'].update('You entered {}'.format(values["-IN-"]))
   elif event == 'Erase':
      window['-OUTPUT-'].update('')
      window['-IN-'].update('')
window.close()

它将产生以下输出窗口:

多个窗口

异步窗口

Window 类的read ()方法具有以下附加参数 -

window.read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)

超时参数允许您的 GUI 在非阻塞读取情况下使用这是您的设备在返回之前可以等待的毫秒数。它创建一个定期运行的窗口。

添加超时值的时间越长,占用的 CPU 时间就越少。在超时时间内,您将“让出”处理器来执行其他任务。与使用非阻塞读取相比,您的 GUI 的响应速度会更快。

timeout_key 参数有助于判断在规定时间内是否有任何用户操作。“timeout_key”的默认值为“__timeout__”。

while True:
   event, value = window.read(timeout=10)
   if event == sg.WIN_CLOSED:
      break
   if event == sg.TIMEOUT_KEY:
      print("Nothing happened")

要使窗口可移动,请将 Window 对象的“grab_anywhere”属性设置为 true。如果“keep_on_top”属性设置为True,则窗口将保持在当前窗口之上。

PySimpleGUI - 元素类

PySimpleGUI 库由许多可以放置在 Window 对象之上的 GUI 小部件组成。例如,我们在上面的示例中使用的按钮或文本框。所有这些小部件实际上都是该库中定义的类的对象,其中 Element 类充当所有其他小部件类的基础。

此 Element 类的对象从未显式声明。它定义了常见属性,如大小、颜色等。这是可用小部件(也称为元素)的列表

先生。 小部件和描述
1 文本元素

在窗口中显示一些文本。通常这意味着单行文本。

2 输入元素

显示单个文本输入字段。

3 多行元素

显示和/或读取多行文本。这既是输入又是输出元素。

4 组合元素

单行输入和下拉菜单的组合。

5 选项菜单元素

类似于组合。仅在 TKinter 端口上

6 复选框元素

显示一个复选框及其旁边的文本。

7 无线电元件

在一组其他无线电元素中使用,使用户能够在选项列表中仅选择一个选项。

8 自旋元件

带有向上/向下按钮和一行文本的微调器。

9 按钮元素

定义所有可能的按钮。Submit、FileBrowse 等快捷方式各创建一个 Button

10 按钮菜单元素

创建一个按钮,单击该按钮将显示类似于右键单击菜单的菜单。

11 滑块元素

用于增加/减少值的水平或垂直滑块。

12 列表框元素

提供值列表供用户选择一个或多个。执行window.read()时返回选定行的列表。

13 图像元素

在窗口中显示图像。只能是 GIF 或 PNG。

14 图形元素

创建绘制图形的区域

15 画布元素

绘制形状的区域

16 进度条元素

显示一个彩色条,该条随着某些操作的进展而变暗。

17 号 表元素

以行和列显示数据

18 树元素

以树状方式呈现数据,很像文件/文件夹浏览器。

19 尺寸调整元件

该元素用于添加更多空间。

20 状态栏元素

StatusBar 元素在底部创建凹陷的文本填充条。

21 框架元素

Frame 元素是一个容器对象,它保存或多个其他类型的元素。

22 列元素

如果您想要设计以一列或多列垂直列表示的 GUI 窗口元素,它会非常有用。

23 选项卡元素

Tab 元素的使用使得设计非常方便、有效且易于用户导航。Tab 元素也是一个容器元素,例如 Frame 或 Column。

元素类的属性

以下是元素类的属性 -

先生。 属性及描述
1 尺寸

(w=字符宽,h=行高)

2 字体

指定字体系列、大小

3 背景颜色

背景颜色

4 文字颜色

元素的文本颜色

5 钥匙

识别一个元素

6 可见的

设置元素的可见性状态(默认= True)

元素类的方法

以下是元素类的方法 -

先生。 方法及说明
1 设置工具提示()

由应用程序调用以更改元素的工具提示文本

2 设置焦点()

将当前焦点设置在此元素上

3 设置大小()

将元素的大小更改为特定大小

4 获取大小()

返回元素的大小(以像素为单位)

5 扩张()

使元素扩展以填充 X 和 Y 方向上的可用空间

6 设置光标()

设置当前元素的光标

7 设置右键单击菜单()

设置单击时调用的右键菜单

PySimpleGUI - 事件

任何 GUI 应用程序都是事件驱动的,能够响应 GUI 元素上发生的各种可能的事件。在 PySimpleGUI 中,事件处理是在 GUI 设计构成下的无限循环内完成的,不断检查事件是否发生并根据事件执行操作。

有两种类型的事件 -

  • 窗口事件,以及

  • 元素事件。

窗口事件默认启用,包括按钮事件(单击任何按钮时发生)和单击标题栏上的“X”按钮事件。

默认情况下不启用元素事件。仅当创建元素时将“enable_events”参数设置为 True 时,才能检测到特定于元素的事件。

窗口关闭事件

当用户按下“X”按钮或执行 Window 类的close()方法时,使 PySimpleGUI 窗口持久化的无限事件循环将终止。终止循环的标准方法如下 -

import PySimpleGUI as psg
...
while True:
 ...

   if event == psg.WIN_CLOSED:
      break
 ...
window.close()

如果此参数设置为 True,则 Widow 类还会发出“enable_close_attempted_event”。当在循环内检测到它时,调用 yes-no 弹出窗口是一个很好的做法。

window = psg.Window('Calculator', layout,  enable_close_attempted_event=True)
while True:
   event, values = window.read()
   print(event, values)
   if event == "Add":
      result = int(values['-FIRST-']) + int(values['-SECOND-'])
   if event == "Sub":
      result = int(values['-FIRST-']) - int(values['-SECOND-'])
   window['-OUT-'].update(result)
   if event == psg.WINDOW_CLOSE_ATTEMPTED_EVENT and psg.popup_yes_no('Do you really want to exit?') == 'Yes':
      break
   if event == psg.WIN_CLOSED or event == 'Exit':
      break

在这种情况下,当按下“X”按钮时,会出现带有是/否按钮的弹出窗口,并且当单击“是”按钮时程序退出。

它将产生以下输出窗口 -

窗口关闭事件

该事件值还返回“-WINDOW CLOSE ATTEMPTED-”值。

-WINDOW CLOSE ATTEMPTED- {'-FIRST-': '200', '-SECOND-': '300'}

按钮事件

按钮单击事件默认启用。要禁用,请使用“Button.update(disabled=True)”。您还可以在 Button 的构造函数中设置“enable_events=True”,它将启用 Button Modified 事件。当某些内容“写入”按钮时会触发此事件。

当我们读取窗口的内容时(使用“window.read()”),按钮值将是其标题(如果未设置 key)或 key(如果已设置)。

在上面的示例中,由于未在“添加”和“子”按钮上设置 key 参数,因此在读取窗口时将返回它们的标题。

Add {'-FIRST-': '200', '-SECOND-': '300'}

将关键参数添加到程序中的“添加”和“子”按钮。

import PySimpleGUI as psg
layout = [
   [psg.Text('Enter a num: '), psg.Input(key='-FIRST-')],
   [psg.Text('Enter a num: '), psg.Input(key='-SECOND-')],
   [psg.Text('Result : '), psg.Text(key='-OUT-')],
   [psg.Button("Add", key='-ADD-'), psg.Button("Sub", key='- SUB-'), psg.Exit()],
]
window = psg.Window('Calculator', layout)
while True:
   event, values = window.read()
   print(event, values)

   if event == "-ADD-":
      result = int(values['-FIRST-']) + int(values['-SECOND-'])

   if event == "-SUB-":
      result = int(values['-FIRST-']) - int(values['-SECOND-'])

   window['-OUT-'].update(result)

   if event == psg.WIN_CLOSED or event == 'Exit':
      break
window.close()

read() 方法返回的元组现在将显示按下的按钮的键。

-ADD- {'-FIRST-': '200', '-SECOND-': '300'}

其他元素的事件

当发生某种类型的用户交互时,许多元素都会发出事件。例如,当移动滑块、选择列表中的项目或单击单选按钮时。

与按钮或窗口不同,默认情况下不启用这些事件。要启用元素的事件,请设置参数“enable_events=True”。

下表显示了元素以及它们生成的事件。

姓名 活动
输入文本 按下任意键
组合 已选择项目
列表框 选择已更改
收音机 选择已更改
复选框 选择已更改
旋转器 已选择新项目
多线 按下任意键
文本 点击
状态栏 点击
图形 点击
图形 拖拽
图形 拖动结束(鼠标向上)
选项卡组 单击了选项卡
滑块 滑块已移动
桌子 已选择行
选定的节点
按钮菜单 已选择菜单项
右键菜单 已选择菜单项

PySimpleGUI - 菜单栏

大多数桌面应用程序都有一个菜单系统,可以根据用户在菜单中选择的选项来触发不同的操作。在典型的应用程序窗口中,菜单栏位于标题栏的正下方和窗口客户区的上方。

菜单栏是由可单击按钮组成的水平栏。单击这些按钮中的任何一个时,都会生成一个选项按钮的下拉列表。这样的选项按钮会触发可以在事件循环内处理的单击事件。

菜单系统的设计与窗口布局的指定相同。它也是一个列表的列表。每个列表都有一个或多个字符串。第一级列表的起始字符串是水平菜单栏中出现的按钮的标题。接下来是下拉菜单中选项按钮的标题字符串列表。这些选项标题位于第一级列表内的列表中。

您可能在选项按钮下有一个子菜单,在这种情况下,标题将放在第三级列表中。同样,标题可以嵌套到任何级别。

菜单定义的一般格式如下:

menu_def = [
   ['Memu1', ['btn1', 'btn2', 'btn3', 'btn4',]],
   ['menu2', ['btn5', 'btn6','btn7', 'btn8'],],
]

要将菜单系统附加到 PysimpleGUI 窗口的主布局,请将 Menu 对象放置在布局的第一行。

Menu 构造函数以menu_def列表作为参数。主布局的其他行可以在具有菜单对象的行之后给出。

layout= [[psg.Menu(menu_def),[..], [..]]

在下面给出的代码中,我们有一个带有“文件”、“编辑”和“帮助”菜单的菜单栏,每个菜单栏中都有一些菜单按钮。

import PySimpleGUI as psg
menu_def = [['File', ['New', 'Open', 'Save', 'Exit', ]], ['Edit', ['Cut', 'Copy', 'Paste', 'Undo'], ],  ['Help', 'About...'], ]
layout = [[psg.Menu(menu_def)],
   [psg.Multiline("", key='-IN-',
   expand_x=True, expand_y=True)],
   [psg.Multiline("", key='-OUT-',
   expand_x=True, expand_y=True)],
   [psg.Text("", key='-TXT-',
   expand_x=True, font=("Arial Bold", 14))]
]
window = psg.Window("Menu", layout, size=(715, 300))
while True:
   event, values = window.read()
   print(event, values)

   if event != psg.WIN_CLOSED:
      window['-TXT-'].update(values[0] + "Menu Button Clicked")
   if event == 'Copy':
      txt = window['-IN-'].get()
   if event == 'Paste':
      window['-OUT-'].update(value=txt)
   if event == psg.WIN_CLOSED:
      break
window.close()

在菜单栏下方,放置了两个多行元素。最后一行有一个 Text 元素。

当单击任何菜单选项按钮时,生成的事件就是该按钮的标题。此标题显示在最后一行的文本标签上。参考下图 -

菜单栏显示

当复制事件发生时,带有 -INkey 的上部多行框中的文本将存储在 txt 变量中。然后,当按下“粘贴”按钮时,-OUT- 框将更新为 txt 的值。

菜单栏编辑

带热键的菜单按钮

要将菜单按钮映射到键盘上的某个键,请在所需字符前放置一个与号 & 字符。例如,将 & 放在 File 之前,则字符串为 '&File'。通过这样做,可以通过按“Alf+F”键访问文件菜单。这里的“F”键被称为热键。

将热键添加到菜单定义中的菜单按钮。

menu_def = [
   ['&File', ['&New', '&Open', '&Save', 'E&xit',]],
   ['&Edit', ['C&ut', '&Copy','&Paste', '&Undo'],],
   ['&Help', '&About...'],
]

运行代码时,菜单中的热键显示为下划线。

菜单按钮热键

右键菜单

该菜单与应用程序窗口顶部的菜单栏分离。每当用户按下鼠标右键时,该菜单就会在单击发生的位置弹出。

在上面定义的菜单栏中,每个列表都是单个菜单的定义。这样的单个菜单定义可以通过构造函数中的 right_click_menu 参数附加到任何元素。该参数也可以在构造主 Window 对象时传递。

让我们使用 rightclick 作为与编辑菜单对应的列表的变量。

rightclick=['&Edit', ['C&ut', '&Copy','&Paste', '&Undo']]
menu_def = [
   ['&File', ['&New', '&Open', '&Save', 'E&xit',]], rightclick,
   ['&Help', '&About...'],
]

将其用作 Window 构造函数中 right_click_menu 参数的值。请参阅以下代码片段 -

window=psg.Window("Menu", layout, size=(715, 300), right_click_menu=rightclick)

进行这些更改并运行代码。单击窗口中的任意位置。弹出菜单如图所示 -

右键菜单

按钮菜单

该菜单与右键菜单类似,只不过它附加到按钮上并在单击按钮时弹出。

在主布局的最后一行,我们添加一个 ButtonMenu 元素并使用右键列表作为其布局。

layout= [
   [psg.Menu(menu_def)],
   [psg.Multiline("", key='-IN-', expand_x=True, expand_y=True)],
   [psg.Multiline("", key='-OUT-', expand_x=True, expand_y=True)],
   [psg.Text("", key='-TXT-', expand_x=True, font=("Arial Bold", 14)),
   psg.ButtonMenu('ButtonMenu', rightclick, key='-BMENU-')]
]

单击右下角的按钮时,会出现菜单,如下图所示 -

按钮菜单

PySimpleGUI - Matplotlib 集成

当从 Python shell 使用 Matplotlib 时,绘图将显示在默认窗口中。backend_tkagg模块对于在 Tkinter嵌入绘图非常有用。

PySimpleGUI 中的 Canvas 元素具有 TKCanvas 方法,该方法返回原始 TKinter 的 Canvas 对象。它被交给backend_tkagg 模块中的FigureCanvasTkAgg()函数来绘制图形。

首先,我们需要使用Figure()类创建图形对象并为其绘图。我们将绘制一个显示正弦波的简单图。

fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))

定义一个函数在画布上绘制 matplotlib 图形对象

def draw_figure(canvas, figure):
   figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
   figure_canvas_agg.draw()
   figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
   return figure_canvas_agg

通过调用 PySimpleGUI.Canvas 对象的 TkCanvas 属性来获取 Canvas。

layout = [
   [psg.Text('Plot test')],
   [psg.Canvas(key='-CANVAS-')],
   [psg.Button('Ok')]
]

通过调用上面的函数来绘制图形。将 Canvas 对象和 fiture 对象传递给它。

fig_canvas_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig)

示例:绘制正弦波线图

完整的代码如下 -

import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import
FigureCanvasTkAgg
import PySimpleGUI as sg
import matplotlib
matplotlib.use('TkAgg')
fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100)
t = np.arange(0, 3, .01)
fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t))
def draw_figure(canvas, figure):
   tkcanvas = FigureCanvasTkAgg(figure, canvas)
   tkcanvas.draw()
   tkcanvas.get_tk_widget().pack(side='top', fill='both', expand=1)
   return tkcanvas
layout = [[sg.Text('Plot test')],
   [sg.Canvas(key='-CANVAS-')],
   [sg.Button('Ok')]]
window = sg.Window('Matplotlib In PySimpleGUI', layout, size=(715, 500), finalize=True, element_justification='center', font='Helvetica 18')

# add the plot to the window
tkcanvas = draw_figure(window['-CANVAS-'].TKCanvas, fig)
event, values = window.read()
window.close()

生成的图表如下 -

正弦波图

PySimpleGUI - 使用 PIL

Python Imaging Library 是一个免费的、跨平台的、开源的 Python 编程语言库,具有打开、操作和保存多种不同图像文件格式的功能。

要安装它,请使用 PIP 命令,如下所示 -

pip3 install pillow

在下面的示例中,我们使用 PIL 函数获取 PNG 图像的字节值,并将其显示在 PySimpleGUI 窗口上的 Image 元素中。

import PySimpleGUI as sg
import PIL.Image
import io
import base64
def convert_to_bytes(file_or_bytes, resize=None):
   img = PIL.Image.open(file_or_bytes)
   with io.BytesIO() as bio:
      img.save(bio, format="PNG")
      del img
      return bio.getvalue()

imgdata = convert_to_bytes("PySimpleGUI_logo.png")
layout = [[sg.Image(key='-IMAGE-', data=imgdata)]]
window = sg.Window('PIL based Image Viewer', layout,resizable=True)
while True:
   event, values = window.read()
   if event == sg.WIN_CLOSED:
      break
window.close()

它将产生以下输出窗口 -

与太平船务合作

PySimpleGUI - 调试器

除了 PyCharm 或 VS Code 等大多数 IDE 具有的内置调试器之外,PySimpleGUI 还提供自己的调试器。该调试器使您能够在代码运行时“查看”代码并与之交互。

为了有效地使用调试器服务,窗口应该异步变红,即,您应该为read()函数提供超时。

通过在程序内的任何位置调用show_debugger_window()函数来调用调试器窗口,如下所示 -

import PySimpleGUI as sg
sg.show_debugger_window(location=(10,10))
window = sg.Window('Debugger Demo',
   [[sg.Text('Debugger'),
   sg.Input('Input here'),
   sg.Button('Push Me')]]
)
while True:
   event, values = window.rea