PySimpleGUI - Window 窗口类

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

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

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


布局结构

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

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

布局

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

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

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)

这将显示所需的窗口。 用户输入存储在名为值的字典中。 当用户按下 Ok 按钮时调用 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"按钮。 这些值将打印如下 −

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

如果在填完数据后,点击"Cancel"按钮,打印的结果会是 −

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

持久窗口

请注意,只要单击任何按钮(或标题栏中的"X"按钮),此窗口就会关闭。 要使窗口保持活动状态,直到按下称为"退出"的特殊类型的按钮,或者如果通过按"X"关闭窗口,read() 方法被置于一个无限循环中,并规定在发生 WIN_CLOSED 事件(按下退出按钮时)或发生退出事件(按下"X"按钮时)时中断。

让我们将上面代码中的 Cancel 按钮更改为退出按钮。

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 类还有其他方法来自定义外观和行为。 它们列在下面 −

序号 方法 & 描述
1 AddRow

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

2 AddRows

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

3 close

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

4 disable

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

5 disappear

使窗口从屏幕上"消失",但保留在任务栏上。

6 enable

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

7 fill

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

8 find_element

查找与提供的键关联的元素对象。 它等同于"element = window[key]"

9 get_screen_dimensions

获取屏幕尺寸。

10 hide

从屏幕和任务栏中隐藏窗口

11 load_from_disk

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

12 layout

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

13 read

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

14 reappear

使消失的窗口再次显示。

15 save_to_disk

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

16 set_title

更改任务栏中窗口的标题


用 Key 键更新窗口

用户在窗口布局上的不同输入元素中输入的数据以字典格式存储。 字典键编号(从 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']

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

key 参数应该是一个字符串。 约定是它应该是一个大写字符串,前后跟一个"-"字符(例如:"- NAME-")。 但是,可以使用任何字符串。

让我们为上面示例中的 Input 元素分配键,如下所示 −

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() 方法之后返回的值字典将包含 key 键标识符,而不是之前的整数。

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

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

让我们扩展之前的示例,在 Ok 和 Cancel 按钮之前添加一行,并有一个带有"-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()

运行上面的代码,在三个input元素中输入文本,然后按OK。 -OUT- 文本标签将更新为此处所示 −

更新窗口

另一个使用 key 属性的例子如下。 Input 元素被分配 key 参数 -FIRST- 和 -SECOND-。 有两个标题为 Add 和 Sub 的按钮。 文本元素根据按下的按钮显示两个数字的加法或减法。

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()

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

更新窗口

无边框窗口

默认情况下,应用程序窗口在客户区上方创建一个标题栏,其中所有其他元素都放置在布局中。标题栏由左侧的窗口标题和右侧的控制按钮(最小化、恢复/最大化和关闭)组成。 然而,特别是对于类似 kiosk 的应用程序,不需要标题栏。 您可以通过将 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) 结构的元组。

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)

timeout 参数让您的 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,窗口将保持在当前窗口之上。