PySimpleGUI 窗口类
弹出窗口有一个预定义的按钮、文本标签和文本输入字段的配置。窗口类允许你设计一个设计更灵活的GUI。除了这些元素外,其他元素如列表框、复选框、单选按钮等都可以使用。你还可以为GUI提供一个菜单系统。某些专门的部件,如旋转器、滑块等,也可以用来使设计更加有效。
一个窗口可以是一个非持久性的窗口,类似于弹出式窗口。它阻断程序流程,直到用户通过点击客户区的一个按钮或标题栏的关闭(X)按钮来关闭它。
另一方面,一个持久的窗口继续可见,直到导致它被关闭的事件发生。异步窗口是指其内容定期更新的窗口。
布局结构
元素或部件在窗口客户区的位置是由列表对象的列表控制的。每个列表元素对应于窗口表面的一行,并可能包含一个或多个PySimpleGUI库中的GUI元素。
第1步是通过画图来可视化元素的位置,如下图所示
窗口上的元素被放置成四行。前三行有一个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 = psg.Window('Form', layout)
这将显示所需的窗口。用户的输入被存储在一个名为value的字典中。当用户按下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'}
If, after filling the data, you press the “Cancel” button, the result printed will be −
Cancel {0: 'Kiran Gupta', 1: 'Mumbai', 2: 'kiran@gmail.com'}
持久窗口
注意,一旦点击任何按钮(或标题栏中的 “X “按钮),这个窗口就会被关闭。为了保持窗口的活力,直到一个特殊类型的按钮被按下,或者窗口被按下 “X “关闭, read() 方法被置于一个无限循环中,当WIN_CLOSED事件发生(当Exit按钮被按下)或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() 方法,用来收集所有输入元素中输入的值。窗口类还有其他方法来定制外观和行为。它们被列举如下
序号 | 方法和描述 |
---|---|
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 改变任务栏中窗口的标题 |
用密钥更新窗口
用户在窗口布局上的不同输入元素中输入的数据是以字典格式存储的。字典中的键被编号(从0开始),从左到右、从上到下对应于输入元素。我们可以通过字典运算符来引用输入数据。这意味着,第一个元素中的数据由 “values[0]”返回。
values = {0: 'kiran', 1: 'Mumbai', 2: 'kiran@gmail.com'}
data = [values[k] for k in values.keys()]
print (data)
It will print the following on the console −
['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() 方法之后返回的value dictionary将包含key identifiers,而不是之前的整数。
OK {'-NM-': 'Kiran', '-AD-': 'Mumbai', '-ID-': 'kiran@gmail.com'}
现在,values[-NM-‘]将获取’Kiran’。这个键可以被分配给任何元素,而不仅仅是输入元素。你可以使用相同的键来调用一个元素的更新。我们可以使用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-文本标签将被更新,如下面所示
下面是使用关键属性的另一个例子。输入元素被分配了关键参数-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()
下面的屏幕截图显示了按下 “添加 “按钮后的结果。
无边界窗口
默认情况下,应用程序窗口在客户端区域上方创建了一个标题栏,所有其他元素都放置在布局中。标题栏由左边的窗口标题和右边的控制按钮(最小化、恢复/最大化和关闭)组成。然而,特别是对于一个类似信息亭的应用程序来说,没有必要设置标题栏。你可以通过将窗口对象的 “no_titlebar “属性设置为 “True “来摆脱标题栏。
要终止这样一个应用程序,必须在Exit按钮事件发生时终止事件循环。
关闭功能失效的窗口
如果你想阻止用户最小化应用程序的窗口,Window对象的 “disable_minimize “属性应该被设置为True。同样,如果 “disable_close “属性的值为 “True”,关闭按钮就会显示,但它不会产生WINDOW_CLOSED事件。
透明的窗口
窗口对象的 “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")
要使窗口可移动,将窗口对象的 “grab_anywhere “属性设置为 “true”。如果 “keep_on_top “属性被设置为 “True”,该窗口将保持在当前窗口的上方。