pysimplegui之第一个程序,包括回调函数,事件,阻塞等待内容


自定义窗口 API 调用(您的第一个窗口)

总结一下:我遇到的坑,

比如拿输入框的内容的时候可以直接通过value[key]

几种窗口模式就是什么时候用timeout这个参数

关闭窗口可以的一边形式

if event in ('EXIT', None):
break

这是这个 GUI 编程的有趣部分。为了真正充分利用 API,您应该使用支持自动完成或显示函数定义的 IDE。这将使定制变得更加顺畅。

关于自定义窗口的第一部分是针对典型的、阻塞的、非持久性窗口的。我的意思是,当您“显示”窗口时,该函数将不会返回,直到用户单击按钮或使用 X 关闭窗口。

存在另外两种类型的窗口。1. 持久窗口——Window.read()方法返回,窗口继续可见。这对于诸如聊天窗口或计时器之类的应用程序或任何在屏幕上保持活动一段时间的应用程序都非常有用。2. 异步窗口——最棘手的。必须非常小心。例如 MP3 播放器或状态仪表板。异步窗口会定期更新(刷新)。timeout你可以很容易地发现它们,因为它们在调用 read 时会有一个参数。event, values = window.read(timeout=100)

立即开始调整您可以使用的每一件小事既不愉快也没有帮助。做一些简单的窗户。使用 Cookbook 和演示程序作为学习方式和“起点”。

橱窗设计师

对于 GUI 编程新手来说,好消息是 PySimpleGUI 有一个窗口设计器。更好的是,窗口设计师无需培训,无需下载,而且每个人都知道如何使用它。

gui0_1

这是一个手动过程,但如果您按照说明进行操作,只需一分钟即可完成,结果将是一个漂亮的 GUI。您将采取的步骤是: 1. 在纸上画出您的 GUI 2. 将您的 GUI 分成几行 3. 用元素名称标记每个元素 4. 使用标签作为伪代码编写 Python 代码

让我们举几个例子。

输入数字.... 流行的初学者程序通常基于要求用户输入某些内容(例如数字)的游戏或逻辑谜题。“高低”答案游戏浮现在脑海中,您尝试根据高低提示猜测数字。

第 1 步 - 绘制 GUI gui1_1

第 2 步 - 分成几行

gui2_1

第 3 步 - 标签元素

gui6_1

第 4 步 - 编写代码 我们正在编写的代码是 GUI 本身的布局。本教程只关注编写窗口代码,而不是显示它的东西,获得结果。

我们在第一行只有一个元素,一些文本。行被写成一个“元素列表”,所以我们需要 [ ] 来创建一个列表。这是第 1 行的代码

[ sg.Text('Enter a number') ]

第 2 行有 1 个元素,一个输入字段。

[ sg.Input() ]

第 3 行有一个确定按钮

[ sg.OK() ]

现在我们已经定义了 3 行,它们被放入一个代表整个窗口的列表中。

layout = [ [sg.Text('Enter a Number')],
           [sg.Input()],
           [sg.OK()] ]

最后我们可以把它们放在一个程序中来显示我们的窗口。

import PySimpleGUI as sg

layout = [[sg.Text('Enter a Number')],
          [sg.Input()],
          [sg.OK()] ]

window = sg.Window('Enter a number example', layout)

event, values = window.read()

window.close()

sg.Popup(event, values[0])

您的调用read通常会返回一个字典,但在您访问它的方式上会“看起来像一个列表”。第一个输入字段将是条目 0,下一个是 1,等等。稍后您将了解key允许您使用自己的值来识别元素而不是为您编号的参数。

示例 2 - 获取文件名

假设您已经编写了一个对某个输入文件进行操作的实用程序,并且您准备好使用 GUI 输入而不是文件名而不是命令行。按照与上一个示例相同的步骤 - 在纸上绘制窗口,将其分成几行,标记元素。

gui4_1 gui5_1

为这个编写代码同样简单。有一个棘手的事情是浏览文件按钮。值得庆幸的是,PySimpleGUI 负责将其与旁边的输入字段相关联。结果,代码看起来几乎和纸上的窗口一模一样。

import PySimpleGUI as sg

sg.theme('Dark Blue 3')  # please make your windows colorful

layout = [[sg.Text('Filename')],
            [sg.Input(), sg.FileBrowse()],
            [sg.OK(), sg.Cancel()] ]

window = sg.Window('Get filename example', layout)
event, values = window.read()
window.close()

sg.Popup(event, values[0])

继续阅读有关显示窗口并返回结果的调用的详细说明。

复制这些设计模式!

您的所有 PySimpleGUI 程序都将使用这两种设计模式中的一种,具体取决于您正在实现的窗口类型。

从版本 4.19.0 开始,常量 WIN_CLOSED 被替换为使用通知None窗口已关闭的事件。

模式 1 A - “One-shot Window” - 一次读取一个窗口然后关闭它

如果您不使用“事件循环”(不多次读取窗口),这将是您将遵循的最常见模式。窗口被读取并关闭。

窗口中的输入字段将作为字典返回给您(在语法上它看起来就像一个列表查找)

import PySimpleGUI as sg

sg.theme('Dark Blue 3')  # please make your windows colorful

layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
                 [sg.InputText(), sg.FileBrowse()],
                 [sg.Submit(), sg.Cancel()]]

window = sg.Window('SHA-1 & 256 Hash', layout)

event, values = window.read()
window.close()

source_filename = values[0]     # the first input element is values[0]

模式 1 B - “One-shot Window” - 一次读取一个窗口然后关闭它(压缩格式)

与模式 1 相同,但以高度紧凑的方式完成。此示例使用close参数 inwindow.read作为读取操作的一部分自动关闭窗口(版本 4.16.0 中的新功能)。这使您能够编写将创建、显示、收集输入和关闭窗口的单行代码。真的是很强大的东西!

import PySimpleGUI as sg

sg.theme('Dark Blue 3')  # please make your windows colorful

event, values  = sg.Window('SHA-1 & 256 Hash', [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
                        [sg.InputText(), sg.FileBrowse()],
                        [sg.Submit(), sg.Cancel()]]).read(close=True)

source_filename = values[0]     # the first input element is values[0]

模式 2 A - 持久窗口(使用事件循环进行多次读取)

一些更高级的程序在屏幕上保持可见的窗口运行。输入值被收集,但不是关闭窗口,而是保持可见,作为向用户输出信息和收集输入数据的一种方式。

此代码将显示一个窗口并打印值,直到用户单击退出按钮或使用 X 关闭窗口。

import PySimpleGUI as sg

sg.theme('Dark Blue 3')  # please make your windows colorful

layout = [[sg.Text('Persistent window')],
          [sg.Input()],
          [sg.Button('Read'), sg.Exit()]]

window = sg.Window('Window that stays open', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    print(event, values)

window.close()

模式 2 B - 持久窗口(使用事件循环进行多次读取 + 更新窗口中的数据)

这是一个稍微复杂但可能更现实的版本,它读取用户的输入并将该输入显示为窗口中的文本。您的程序可能会同时执行这两项活动(输入和输出),因此这将为您提供一个很大的起点。

不要担心所有这些陈述的含义。只需复制它,以便您可以开始使用它,进行一些更改。实验看看事情是如何工作的。

这个例子介绍了“键”的概念。键在 PySimpleGUI 中非常重要,因为它们使您能够使用您想要使用的名称来识别和使用元素。键可以是(几乎)任何东西,除了None列表(元组很好)。要访问在下面的示例中读取的输入元素的数据,您将使用values['-IN-']而不是values[0]像以前一样。

import PySimpleGUI as sg

sg.theme('Dark Blue 3')  # please make your windows colorful

layout = [[sg.Text('Your typed chars appear here:'), sg.Text(size=(12,1), key='-OUTPUT-')],
          [sg.Input(key='-IN-')],
          [sg.Button('Show'), sg.Button('Exit')]]

window = sg.Window('Window Title', layout)

while True:  # Event Loop
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED or event == 'Exit':
        break
    if event == 'Show':
        # change the "output" element to be the value of "input" element
        window['-OUTPUT-'].update(values['-IN-'])

window.close()

Qt 设计器

实际上有一个使用 Qt 的窗口设计器的 PySimpleGUI 窗口设计器。然而,这超出了本文档的范围。您可以在这里找到该项目:https://github.com/nngogol/PySimpleGUIDesigner

我希望尽快开始使用它。

Python 中的 GUI 编程应该是什么样子?至少对于初学者?

虽然一个目标是让创建 GUI 变得简单,但另一个同样重要的目标是以 Python 风格的方式完成它。它是否实现了这些目标还有待商榷,但同样是一次尝试。

PySimpleGUI 中自定义窗口的关键是将窗口视为 GUI 元素的 ROWS。每一行都被指定为这些元素的列表。把这些行放在一起,你就有了一个窗口。这意味着 GUI 被定义为一系列列表,这是一种查看事物的 Python 方式。

让我们剖析一下这个小程序

import PySimpleGUI as sg

sg.theme('Dark Blue 3')  # please make your windows colorful

layout = [[sg.Text('Rename files or folders')],
      [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()],
      [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()],
      [sg.Submit(), sg.Cancel()]]

window = sg.Window('Rename Files or Folders', layout)

event, values = window.read()
window.close()
folder_path, file_path = values[0], values[1]       # get the data from the values dictionary
print(folder_path, file_path)

主题

图片

导入后的第一行代码是对theme.

在 2019 年 12 月之前,PySimpleGUI 中特定“主题”的方式是调用change_look_and_feel该调用已被更简单的函数所取代theme

窗口内容(布局)

让我们同意窗口有 4 行。

第一行只有文字Rename files or folders

第二行有 3 个元素。首先是text Source for Folders,然后是输入字段,然后是浏览按钮。

现在让我们看看 Python 代码中的这两行和另外两行如何:

layout = [[sg.Text('Rename files or folders')],
          [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()],
          [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()],
          [sg.Submit(), sg.Cancel()]]

看看源代码如何反映布局?您只需为每一行创建列表,然后将该表提交给 PySimpleGUI 以显示和获取值。

那么这些返回值呢?大多数人只是想显示一个窗口,获取输入值并用它们做一些事情。那么,当我只想将窗口的输入值提供给我时,为什么要将代码分解为按钮回调等。

对于返回值,从上到下、从左到右扫描窗口。作为输入字段的每个字段都将在返回值中占据一个位置。

在我们的示例窗口中,有 2 个字段,因此该窗口的返回值将是一个包含 2 个值的字典。请记住,如果您key在创建元素时未指定 a,则会为您创建一个。它们是从 0 开始的整数。在这个例子中,我们有 2 个输入元素。它们可以作为 values[0] 和 values[1] 寻址

“读取”窗口的值(也显示窗口)

event, values = window.read()
folder_path, file_path = values[0], values[1]

在一个语句中,我们既显示窗口又读取用户的输入。在下一行代码中,返回值字典folder_path被拆分为单独的变量和file_path.

这不是寻找 GUI 的 Python 程序员想要的吗?一些易于使用的东西来获得价值并继续进行程序的其余部分,真正的行动正在发生。当使用 PySimpleGUI 可以在 3 或 4 行代码中实现相同的布局时,为什么还要编写 GUI 代码页面。4行还是40行?大多数人会选择4。

返回值

调用有 2 个返回值Window.read(),一个event导致Read返回,values一个列表或值字典。如果布局中没有带键的元素,那么它将是一个列表。但是,某些元素(例如某些按钮)会自动添加一个键。 最好在所有输入类型元素上使用键。

两个返回值

所有 Window Read 调用都返回 2 个值。按照惯例,会写一个 read 语句:

event, values = window.read()

你不必以这种方式写你的读物。您可以根据需要命名变量。但是,如果您想以其他使用 PySimpleGUI 的程序员习惯的方式对它们进行编码,请使用此语句。

活动

第一个参数event描述了读取完成的原因。事件是其中之一:

对于所有 Windows:

  • 按钮点击
  • 使用 X 关闭窗口

对于专门启用这些的 Windows。请参阅本文档中的相应部分以了解如何启用这些以及事件返回值是什么。

  • 键盘按键
  • 鼠标滚轮向上/向下
  • 已选择菜单项
  • 元素已更改(滑块、微调器等)
  • 单击了列表项
  • 在输入元素中按下了返回键
  • 等待事件超时
  • 文本被点击
  • 选择的组合框项目
  • 已选择表格行
  • 等等。

大多数情况下,事件将是按钮单击或窗口关闭。enable_events=True当您在创建元素时进行设置时,会发生其他元素特定类型的事件

按钮点击事件

默认情况下,按钮将始终返回单击事件,或者在实时按钮的情况下,返回按钮按下事件。您无需执行任何操作即可启用按钮点击。要禁用事件,请使用其 Update 方法禁用按钮。

enable_events=True您可以通过在 Button 调用中设置来启用额外的“Button Modified”事件。这些事件在某个按钮“写入”时触发,通常是因为该按钮在另一个按钮中被列为“目标”。

读取调用的按钮值将是 2 个值之一: 1. 按钮的文本 - 默认 2. 按钮的键 - 如果指定了键

如果按钮在创建时设置了键,则无论按钮上显示什么文本,都将返回该键。如果没有设置键,则返回按钮文本。如果没有单击按钮,但窗口还是返回了,则事件值是导致事件生成的键。例如,如果enable_events在一个Input元素上设置了 并且有人在该Input框中键入了一个字符,那么该事件将是输入框的键。

元素事件

当某些元素发生某些事情时,它们能够生成事件。例如,当滑块移动,或单击列表项或单击表行时。默认情况下不启用这些事件。要为元素启用事件,请设置参数enable_events=True这与旧click_submits参数相同。您会发现该click_submits参数仍在函数定义中。您可以继续使用它。它们是相同的设置。使用两个值的“或”。将来,click_submits 将被删除,因此请将您的代码迁移到使用enable_events.

名称事件
输入文本 任何改变
组合 选择的项目
列表框 选择已更改
收音机 选择已更改
复选框 选择已更改
微调器 选择了新项目
多行 任何改变
文本 点击
状态栏 点击
图形 点击
图形 拖着
图形 拖动结束(鼠标向上)
选项卡组 选项卡点击
滑块 滑块移动
桌子 选择的行
选定的节点
按钮菜单 选择的菜单项
右键菜单 选择的菜单项

其他活动

您将收到 MenuBar 和 ButtonMenu 的键。使用该键读取返回值字典中的值。显示的值将是所选菜单项的全文加键。请记住,您可以将键放在菜单项上。您将在菜单定义中定义文本和键。

右键单击菜单项选择

与菜单栏和按钮菜单不同,您将直接收到菜单项文本及其键值。您不会进行字典查找来获取值。它是从 WindowRead() 返回的事件代码。

Windows - 键盘、鼠标滚轮

Windows 能够返回键盘事件。如果它是特殊键,它们将作为单个字符或字符串返回。我只能说实验。鼠标滚轮事件也是字符串。在您的代码中打印以查看返回的内容。

超时

如果您在读取中设置了超时参数,则将返回系统 TIMEOUT_KEY。如果您在 Read 调用中指定了自己的超时键,则该值将是返回的值。

窗口关闭事件

检测并正确处理正在关闭的 Windows 是 PySimpleGUI 应用程序的重要组成部分。您会在每个演示程序的每个事件循环中找到一个 if 语句,该语句检查表明窗口已关闭的事件。

关闭窗口最明显的方法是单击窗口右上角的“X”(在 Windows、Linux 上……Mac 不使用“X”但仍有关闭按钮)。在 Windows 系统上,键盘键 ALT+F4 将强制窗口关闭。这是不使用鼠标关闭窗口的一种方法。有些程序还可以向窗口发送“关闭”命令。

无论在窗口上如何执行关闭,PySimpleGUI 都会为此关闭返回一个事件。

WIN_CLOSED 事件

当用户单击 X 关闭窗口时,将返回常量 WIN_CLOSED (None)。

通常,关闭窗口的检查发生在window.read()调用返回之后。原因是在关闭的窗口上操作可能会导致错误。检查关闭是一个“if”语句。

始终在事件循环中包含对关闭窗口的检查。

The Window Closed If 语句

您可以在文档和演示程序中找到此 if 语句的 2 种形式。一个是“Pythonic”,另一个更容易被初学者理解。如果窗口同时具有用于指示用户希望退出的按钮,则这是您在 PySimpleGUI 材料中最常看到的格式。在此示例中,我使用了“退出”按钮:

if event == sg.WIN_CLOSED or event == 'Exit':
    break

同一语句的更“Pythonic”版本是:

if event in (sg.WIN_CLOSED, 'Exit'):
    break

如果您在文档中大喊应始终使用第二种形式,请记住许多 PySimpleGUI 用户是 Python 新手。如果他们看到的第一个 PySimpleGUI 程序示例中包含 if 语句,那么他们甚至在开始旅程之前就会立即迷失方向。所以,决定,你猜对了,变得简单。带有“或”的语句更容易理解。

一个完整的例子 - 传统的窗口关闭检查

让我们把这个 if 语句放到上下文中,这样你就可以看到它的去向以及它是如何与事件循环一起工作的

import PySimpleGUI as sg

layout = [[sg.Text('Very basic Window')],
          [sg.Text('Click X in titlebar or the Exit button')],
          [sg.Button('Go'), sg.Button('Exit')]]

window = sg.Window('Window Title', layout)

while True:
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED or event == 'Exit':
        break

window.close()

请注意,while 循环之后的行是对window.close()这样做的原因是退出循环可以有两种方式。* 单击“X” * 单击退出按钮

如果单击退出按钮,窗口仍将打开。养成像这样明确关闭窗户的习惯。

如果用户点击“X”并关闭窗口,那么它就会被底层框架销毁。您应该仍然打电话window.close(),因为可能需要进行清理工作,并且关闭已经关闭的窗口没有害处。

如果您不关闭窗口,tkinter 有时会生成错误/警告。对于其他端口,例如 PySimpleGUIWeb,不关闭窗口可能会导致您的程序继续在后台运行。这可能会导致您的程序不可见,但会占用 100% 的 CPU 时间。对您的用户来说不好玩。

窗口关闭确认

在 4.33.0 中enable_close_attempted_event,向Window对象添加了一个新参数 。此布尔参数指示您是否希望接收用户想要关闭窗口的事件,而不是用户关闭窗口的事件。

要启用此功能,请使用以下Window内容创建:

window = sg.Window('Window Title', layout, enable_close_attempted_event=True)

启用关闭尝试功能后,当用户单击“X”或键入 ALT+F4 时,您不会像以前那样收到 WIN_CLOSED 事件,而是会收到一个事件WINDOW_CLOSE_ATTEMPTED_EVENT并且窗口将保持打开状态。

通常此功能用于添加“关闭确认”弹出窗口。流程是这样的:

  • 显示窗口
  • 用户点击 X
  • 弹出窗口显示消息“您真的要关闭窗口吗?”
  • 如果确认需要关闭,则关闭窗口。它不是,事件循环继续,基本上忽略了发生的事件。

一个完整的例子 - 窗口关闭确认 ( enable_close_attempted_event=True)

回到上面使用的示例,只有 2 处修改。

  1. 将参数添加enable_close_attempted_event=True到调用Window
  2. 事件循环中的 if 语句已更改为添加确认
import PySimpleGUI as sg

layout = [[sg.Text('Very basic Window')],
          [sg.Text('Click X in titlebar or the Exit button')],
          [sg.Button('Go'), sg.Button('Exit')]]

window = sg.Window('Window Title', layout, enable_close_attempted_event=True)

while True:
    event, values = window.read()
    print(event, values)
    if (event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT or event == 'Exit') and sg.popup_yes_no('Do you really want to exit?') == 'Yes':
        break

window.close()

事件循环从这样的检查更改:

    if event == sg.WIN_CLOSED or event == 'Exit':
        break

像这样的人:

    if (event == sg.WINDOW_CLOSE_ATTEMPTED_EVENT or event == 'Exit') and sg.popup_yes_no('Do you really want to exit?') == 'Yes':
        break

让我们运行最后一个程序,这样您就可以看到这一切对用户来说是什么样的。

在用户之前退出窗口的这两种情况下,现在都有一个额外的确认步骤。

下载

演示程序.... PySimpleGUI 程序最好的朋友

与 PySimpleGUI 的所有功能一样,Demo Programs 是可供您了解参数的最佳资源之一,例如这个接近尝试的参数。当您遇到以前未使用过的参数或功能时,查找其使用示例的一种方法是使用演示浏览器搜索演示程序。您将找到 Cookbook 中描述的演示浏览器。

在撰写本文时,演示程序浏览器的名称为:

Browser_START_HERE_Demo_Programs_Browser.py

如果您输入本节中描述的参数 -enable_close_attempted_event您将找到一个使用此参数的演示程序。

演示浏览器

此演示向您展示了与文档本节中使用的代码类似的代码。使用这个浏览器程序!这将使查找示例变得更加容易

values变量 - 以列表形式返回

Read 调用的第二个参数是 Window 上输入字段的列表或字典。

默认情况下,返回值是一个值列表,每个输入字段都有一个条目,但对于除了最简单的窗口之外的所有窗口,返回值将是一个字典。这是因为您可能会在布局中使用“键”。当你这样做时,它会强制返回值是一个字典。

作为输入元素的每个元素都将在返回值列表中具有一个值。如果您确定这些值将作为列表返回,那么您可以变得聪明并直接解压缩到变量中。

event, (filename, folder1, folder2, should_overwrite) = sg.Window('My title', window_rows).read()

或者,更常见的是,您可以单独解压缩返回结果。这是首选方法,因为它适用于列表和字典返回值。

event, values = sg.Window('My title', window_rows).read()
event, value_list = window.read()
value1 = value_list[0]
value2 = value_list[1]
     ...

但是,当您有很多输入字段时,此方法并不好。如果您在窗口中插入一个新元素,那么您将不得不重新整理您的解包,修改每个语句以引用value_list[x].

更常见的方法是通过将键放在“重要”元素(您希望从中获取值并希望与之交互的元素)上,请求您的值作为字典返回

values 变量 - 作为字典返回值

对于那些没有遇到过 Python 字典的人,不要惊慌!只需复制并粘贴示例代码并进行修改即可。遵循这个设计模式,你会没事的。您可能会在此过程中学到一些东西。

对于超过 3 或 4 个字段的窗口,您将需要使用字典来帮助您组织返回值。在几乎所有(如果不是全部)演示程序中,您都会发现返回值作为字典传递。这不是一个很难掌握的概念,语法很容易理解,而且它的代码可读性很强。

您将遇到的最常见的窗口读取语句如下所示:

window = sg.Window("My title", layout).read()

要使用字典,您需要: * 用关键字标记您希望在字典中出现的每个输入元素key

如果窗口中的任何元素具有key,则所有返回值都通过字典返回。如果某些元素没有键,则它们从零开始编号。

让我们看一下您的第一个基于字典的窗口。

import PySimpleGUI as sg

sg.theme('Dark Blue 3')  # please make your windows colorful

layout = [
            [sg.Text('Please enter your Name, Address, Phone')],
            [sg.Text('Name', size=(15, 1)), sg.InputText('1', key='-NAME-')],
            [sg.Text('Address', size=(15, 1)), sg.InputText('2', key='-ADDRESS-')],
            [sg.Text('Phone', size=(15, 1)), sg.InputText('3', key='-PHONE-')],
            [sg.Submit(), sg.Cancel()]
            ]

window = sg.Window('Simple data entry window', layout)
event, values = window.read()
window.close()

sg.Popup(event, values, values['-NAME-'], values['-ADDRESS-'], values['-PHONE-'])

要获取输入字段的值,请使用用作key值的任何值作为索引值。因此要获取名称字段的值,可以写为

values['-NAME-']

以与列表相同的方式考虑变量值,但是,不要使用 0、1、2 来引用列表中的每个项目,而是使用键的值。上面窗口中的 Name 字段由 引用values['-NAME-']

您会发现在大多数 PySimpleGUI 窗口中使用的关键字段非常多,除非窗口非常简单。

您将在许多演示程序中看到的一个约定是键以全部大写字母命名,开头和结尾都带有下划线。您不必这样做...您的键值可能如下所示: key = '-NAME-'

这种命名约定的原因是当你扫描代码时,这些关键值会跳出来。您立即知道这是一把钥匙。尝试扫描上面的代码,看看这些键是否弹出。 key = '-NAME-'

事件循环/回调函数

所有 GUI 都有一个共同点,即“事件循环”。通常 GUI 框架会为您运行事件循环,但有时您需要更大的控制权并会运行您自己的事件循环。在讨论嵌入式系统或 Raspberry Pi 时,您经常会听到术语事件循环。

使用 PySimpleGUI,如果您的窗口在单击按钮后仍保持打开状态,那么您的代码将有一个事件循环。如果您的程序显示一个“一次性”窗口,收集数据然后没有其他 GUI 交互,那么您不需要事件循环。

事件循环没有什么神秘的......它们是你需要处理的循环......等待它......事件事件是诸如按钮单击、击键、鼠标滚轮向上/向下之类的事情。

这个小程序有一个典型的 PySimpleGUI 事件循环。

PySimpleGUI 事件循环的剖析如下,一般来说*实际的“循环”部分是一个while True循环 *“读取”事件和窗口具有的任何输入值 *检查窗口是否关闭或用户希望退出 *一系列if event ....语句

这是一个完整的简短程序来演示这些概念中的每一个。

import PySimpleGUI as sg

sg.ChangeLookAndFeel('GreenTan')

# ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
            ['&Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
            ['&Help', '&About...'], ]

# ------ Column Definition ------ #
column1 = [[sg.Text('Column 1', background_color='lightblue', justification='center', size=(10, 1))],
           [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')],
           [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2')],
           [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]]

layout = [
    [sg.Menu(menu_def, tearoff=True)],
    [sg.Text('(Almost) All widgets in one Window!', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)],
    [sg.Text('Here is some text.... and a place to enter text')],
    [sg.InputText('This is my text')],
    [sg.Frame(layout=[
    [sg.Checkbox('Checkbox', size=(10,1)),  sg.Checkbox('My second checkbox!', default=True)],
    [sg.Radio('My first Radio!     ', "RADIO1", default=True, size=(10,1)), sg.Radio('My second Radio!', "RADIO1")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')],
    [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3)),
     sg.Multiline(default_text='A second multi-line', size=(35, 3))],
    [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(20, 1)),
     sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)],
    [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))],
    [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),
     sg.Frame('Labelled Group',[[
     sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, tick_interval=25),
     sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75),
     sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10),
     sg.Column(column1, background_color='lightblue')]])],
    [sg.Text('_' * 80)],
    [sg.Text('Choose A Folder', size=(35, 1))],
    [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'),
     sg.InputText('Default Folder'), sg.FolderBrowse()],
    [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]]

window = sg.Window('Everything bagel', layout, default_element_size=(40, 1), grab_anywhere=False)
event, values = window.read()
window.close()

sg.Popup('Title',
         'The results of the window.',
         'The button clicked was "{}"'.format(event),
         'The values are', values)

这是一个复杂的窗口,具有相当多的自定义大小以使事物排列整齐。这是您只需编写一次的代码。查看代码时,请记住您看到的是列表列表。每行包含一个用于创建窗口的图形元素列表。如果您看到一对方括号 [ ],那么您就知道您正在阅读其中一行。GUI 的每一行都将是这些列表之一。

这个窗口对你来说可能看起来“丑陋”,这是因为没有做出任何努力让它看起来不错。它纯粹是功能性的。窗口中有 30 个元素。三十个元素。考虑到它的作用,它是神奇的,或者至少令人难以置信的令人印象深刻。为什么?因为在不到 50 行代码中创建、显示、收集结果并在另一个窗口中显示结果。

50 行。如果你能做到的话,你将需要 50 行 tkinter 或 Qt 代码来编写窗口的前 3 个元素。

不,让我们在这里明确一点……这个窗口将使用传统的 Python GUI 包来处理大量代码。这是事实,如果你想证明我错了,那么请务必这样做。请使用 tkinter、Qt 或 WxPython 编写此窗口并发送代码!

请注意,此窗口顶部甚至还有一个菜单栏,很容易错过。

图片

单击提交按钮导致窗口调用返回。对 Popup 的调用导致出现此窗口。

图片

Note, event values can be None的值event将是按钮元素创建时显示的文本或按钮的键。如果用户使用窗口右上角的“X”关闭窗口,eventsg.WIN_CLOSED等于None您的代码 包含sg.WIN_CLOSED.

对于“永久窗口”, 始终为您的用户提供出路否则,您将得到永远无法正确关闭的窗口。您可以在每个演示程序中找到实际上是 2 行代码。当您使用它时,请确保window.close()在您的事件循环之后调用,以便您的窗口确定关闭。

您可以在结果弹出窗口中看到返回的值是一个字典。窗口中的每个输入字段都会在返回值列表中生成一项。输入字段通常返回一个string复选框和单选按钮返回bool根据您的配置方式或您使用的端口,滑块可能返回浮点数或整数。

如果您的窗口没有键并且没有“浏览”类型的按钮,那么它将以列表而不是字典的形式返回值。如果可能,PySimpleGUI 会尝试将值作为列表返回以保持简单。

请注意,在此示例的返回值列表中,许多键是数字。那是因为没有在任何元素上指定键(尽管自动为您创建了一个)。如果您没有为元素指定键,则将按顺序分配一个数字。对于您不打算从中修改或读取值的元素,例如文本元素,您可以跳过添加键。对于其他元素,您可能需要添加键,以便您可以轻松访问这些值并对它们执行操作。

posted @ 2022-01-15 17:27  菩提浪子  阅读(2289)  评论(0编辑  收藏  举报