整理 PySimpleGUI 官方网站
原文google翻译过来的
https://pysimplegui.readthedocs.io/en/latest/
全局设置
有多种自定义PySimpleGUI的方法。具有最细粒度的呼叫(允许访问特定和精确的设置)。
ChangeLookAndFee
l实际上,该呼叫是单个呼叫,可
SetOptions
在其中更改13种不同的设置。
Mac用户 -您无法调用,
ChangeLookAndFeel
但可以
SetOptions
使用任何需要的值集进行调用。没有任何东西被阻止或过滤。
这些设置适用于以后创建的所有窗口。
SetOptions
。选项和元素选项将优先于这些设置。可以将设置视为设置级别,其中窗口级别为最高,元素级别为最低。因此,级别为:
- 全球
- 窗口
- 元件
每个较低级别将覆盖较高级别的设置。更改设置后,在程序执行期间它们将保持更改状态(除非再次更改)。
永久窗口(单击按钮后窗口保持打开状态)
PySimpleGUI的早期版本没有“持久窗口”的概念。用户单击按钮后,窗口将关闭。一段时间后,功能被扩展,因此默认情况下窗口保持打开状态。
自动清除的输入字段
请注意,执行时可以
清除
InputText
和
MultiLine
元素。如果要在a 之后清除输入字段,则可以在创建这些元素时将参数设置为False。清除功能逐个元素打开和关闭。
read
window.read
do_not_clear
这背后的原因是持久性Windows通常是“表单”。当“提交”表单时,您希望所有字段都保留为空白,以便下一个数据输入将从一个新窗口开始。另外,在实现“聊天窗口”类型的界面时,每次读取/发送聊天数据后,都希望清除输入字段。将其视为Texting应用程序。如果要发送第二个文本,是否需要清除以前的文本?
基本的永久窗口设计模式
持久Windows的设计模式已经在文档的前面显示给您了……这里是为了您的方便。
import PySimpleGUI as sg
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()
print(event, values)
if event in (None, 'Exit'):
break
window.close()
读(超时= t,timeout_key = TIMEOUT_KEY,close = False)
Read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)
超时读取对于GUI在非阻塞读取情况下使用是一件非常好的事情。如果您的设备可以稍等片刻,请使用这种读取方法。您可以添加到超时值的时间越长,占用的CPU时间就越少。
在返回之前要等待几毫秒的想法。这是使窗口定期运行的简单方法。
超时读取的一种思考方式:
在超时时间内,您正在“屈服”处理器来执行其他任务。
但是它比仅仅成为一个好公民还要好。… 与
使用非阻塞读取相比,您的GUI响应更快
假设您有一个要每100毫秒“轮询”的设备。“简单的出路”和直到最近的唯一出路是:
# YOU SHOULD NOT DO THIS您不应该这样做
while True: # Event Loop
event, values = window.ReadNonBlocking() # DO NOT USE THIS CALL ANYMORE
read_my_hardware() # process my device here
time.sleep(.1) # sleep 1/10 second DO NOT PUT SLEEPS IN YOUR EVENT LOOP!
该程序将快速测试用户输入,然后处理硬件。然后,它将休眠100毫秒,而gui则没有响应,然后它将再次使用GUI进行登录。
使用PySimpleGUI的更好方法…使用读取超时机制,睡眠消失了。
# This is the right way to poll for hardware这是轮询硬件的正确方法
while True: # Event Loop
event, values = window.read(timeout = 100)
read_my_hardware() # process my device here
此事件循环将每100毫秒运行一次。您正在
read
拨打电话,因此使用该用户所做的任何事情都会立即返回给您,并且您正在等待100毫秒以等待用户执行某项操作。如果用户不执行任何操作,则读取将超时并且执行将返回到程序。
sg.TIMEOUT_KEY
如果您使用具有超时值的读取,则事件值None表示窗口已关闭,就像normal一样
window.read
。剩下的问题是当没有其他事件发生时将其设置为什么。该值将是的值
TIMEOUT_KEY
。如果您在读取调用中未指定timeout_key值,那么它将被设置为默认值:
TIMEOUT_KEY = __timeout__
如果要在循环中测试“无事件”,则将这样编写:
while True:
event, value = window.read(timeout=10)
if event is None:
break # the use has closed the window
if event == sg.TIMEOUT_KEY:
print("Nothing happened")
谨慎使用异步窗口。可能有一个看似异步的窗口,但事实并非如此。 在进入异步窗口之前,请尝试查找其他方法。发出此请求的原因是异步Windows反复轮询tkinter。如果读取中没有超时,并且程序没有其他阻塞,那么您将消耗100%的CPU时间。成为一个好公民很重要。不要不必要地消耗CPU周期。有时您的鼠标想移动您知道吗?
read(timeout=0)
read(timeout=0)
您可能会发现一些PySimpleGUI程序将超时值设置为零。这是非常危险的事情。如果您不喜欢事件循环中的其他内容,那么程序将消耗100%的CPU。请记住,当今的CPU是多核的。在超时为0的情况下运行时,您可能只会看到7%的CPU处于繁忙状态。这是因为任务管理器正在报告系统范围的CPU使用率。您的程序所运行的单核可能是100%。
真正的非阻塞(超时= 0)读取通常保留为“最后手段”。当阻塞读取就可以了,或者读取超时时,人们会使用非阻塞读取的次数太多了。
如果您需要应用程序中每位CPU的强大功能,则将超时值设为零是有效的。也许您的循环正在做一些超级CPU密集型工作,而您的GUI无法使用任何CPU时间。在这种情况下,超时为零是适当的。
成为优秀的计算机公民。以非零超时运行,这样CPU上的其他程序将有时间运行。
小超时值(10ms以下)
不要
使用少于10ms的超时时间。否则,您将无所适从,花时间尝试做一些GUI事情,而在完成任何事情之前,都会被超时计时器打扰。结果可能是灾难性的。
有一种混合方法……读取超时。如果您能够通过使用这种类型的读取来节省更多的CPU时间,那么您将在令人印象深刻的仪表上获得更高的分数。
使用非阻塞窗口的最合法时间是直接使用硬件时。也许您正在驾驶串行总线。如果查看Demo_OpenCV_Webcam.py程序中的事件循环,您会看到该读取是非阻塞读取。但是,事件循环中有一个发生阻塞的地方。循环中要阻止的点是从网络摄像头读取帧的调用。当框架可用时,您希望将其快速传送到输出设备,因此您不希望GUI阻塞。您希望阻止从硬件读取。
在演示中可以找到另一个示例,该示例用于控制Raspberry Pi上的机器人。在该应用程序中,您需要阅读方向按钮,前进,后退等,并立即采取措施。如果您使用的是RealtimeButtons,则目前唯一的选择是使用非阻塞窗口。如果要使按钮具有实时响应性,则必须将超时设置为零。
但是,使用这些按钮,在事件循环中添加睡眠至少将使其他进程有时间执行。但是,它将饿死您的GUI。在您整个睡眠期间,您的GUI均未执行。
定期呼叫Read
假设您最终使用了非阻塞读取…那么您需要做一些内务处理。您可以定期“刷新”可见的GUI。在两次GUI更新之间等待的时间越长,窗口的感觉就越迟钝。由您决定是否进行这些调用,否则您的GUI将冻结。
与非阻塞窗口进行交互的方法有2种。1.像读取普通窗口一样读取该窗口。2.在不读取该窗口的情况下“刷新”该窗口的值。这是一项快速操作,旨在向用户显示最新值
使用异步窗口时,会显示该窗口,可以读取用户输入,但是您的代码会不断变化。您的责任是
PySimpleGUI.read
定期致电。一秒钟几次或更长时间将产生一个相当活泼的GUI。
退出(关闭)永久窗口
如果您的窗口具有关闭该窗口的特殊按钮,则PySimpleGUI将自动为您关闭该窗口。如果您所有的按钮都是普通
Button
元素,那么完成操作就取决于您要关闭窗口。
要关闭窗口,请调用
close
方法。
window.close()
从版本4.16.0开始,您可以
close
在
window.read
调用中使用参数来指示应从读取返回之前关闭窗口。这种功能以极好的方式使单行窗口快速获得信息。
这行代码将显示一个窗口,获取用户的输入,关闭该窗口,然后将值作为事件和值字典返回。
event, values = sg.Window('Login Window',
[[sg.T('Enter your Login ID'), sg.In(key='-ID-')],
[sg.B('OK'), sg.B('Cancel') ]]).read(close=True)
login_id = values['-ID-']
您还可以非常轻松地创建自定义弹出窗口:
long_string = '123456789 '* 40
event, values = sg.Window('This is my customn popup',
[[sg.Text(long_string, size=(40,None))],
[sg.B('OK'), sg.B('Cancel') ]]).read(close=True)
请注意,
None
在这种情况下,size的height参数为。对于PySimpleGUI的tkinter端口,这将导致行数“适合”要显示的字符串的内容。
持久窗口示例-运行更新的计时器
有关异步窗口的另一个示例,请参阅GitHub上名为Demo Media Player的示例代码。我们将创建一个窗口,并每0.01秒更新该窗口的元素之一。这是完成此操作的全部代码。
import PySimpleGUI as sg
import time
# ---------------- Create Form ----------------
sg.ChangeLookAndFeel('Black')
sg.SetOptions(element_padding=(0, 0))
layout = [[sg.Text('')],
[sg.Text(size=(8, 2), font=('Helvetica', 20), justification='center', key='text')],
[sg.Button('Pause', key='button', button_color=('white', '#001480')),
sg.Button('Reset', button_color=('white', '#007339'), key='Reset'),
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
window = sg.Window('Running Timer', layout, no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True)
# ---------------- main loop ----------------
current_time = 0
paused = False
start_time = int(round(time.time() * 100))
while (True):
# --------- Read and update window --------
event, values = window.read(timeout=10)
current_time = int(round(time.time() * 100)) - start_time
# --------- Display timer in window --------
window['text'].update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60,
(current_time // 100) % 60,
current_time % 100))
以前,该程序是通过在循环中使用睡眠来控制时钟滴答来实现的。此版本使用新的超时参数。结果是一个窗口的反应速度比睡眠状态的窗口要快,而且准确性也很高。
而不是非阻塞读取—使用
enable_events = True
或
return_keyboard_events = True
enable_events = True
return_keyboard_events = True
每当您想到“我希望X元素导致Y元素执行某些操作”时,您都想使用该
enable_events
选项。
代替轮询,尝试使窗口返回给您的选项。
通过使用非阻塞窗口,您可以进行轮询。您确实可以通过轮询来创建应用程序。会的。但是,与使用其他技术相比,您将最大限度地利用处理器,甚至可能需要更长的时间对事件做出反应。
例子
一个示例是您有一个输入字段,当您按屏幕键盘上的按钮时,该输入字段会发生变化。
更新元素(在活动窗口中更改元素的值)
如果要在创建窗口后在窗口中更改元素的设置,则将调用元素的
Update
方法。
注意必须先读取或完成
一个窗口,然后才能进行任何更新调用。另外,并非所有创建元素时可用的设置都可以通过其update方法使用。
这是更新文本元素的示例
import PySimpleGUI as sg
layout = [ [sg.Text('My layout', key='-TEXT-')],
[sg.Button('Read')]]
window = sg.Window('My new window', layout)
while True: # Event Loop
event, values = window.read()
if event is None:
break
window['-TEXT-'].update('My new text value')
注意Update调用的位置。如果要在事件循环之外的Read调用之前更新Text Element ,则必须首先在窗口上调用Finalize。
在此示例中,更新是在读取之前完成的。因此,将Finalize调用添加到Window创建中。
import PySimpleGUI as sg
layout = [ [sg.Text('My layout', key='-TEXT-')],
[sg.Button('Read')]]
window = sg.Window('My new window', layout, finalize=True)
window['-TEXT-'].update('My new text value')
while True: # Event Loop
event, values = window.read()
if event is None:
break
永久窗口保持打开状态,因此在读取返回后继续与用户交互。程序通常希望传达结果(输出信息)或更改元素的值(例如填充列表元素)。
您可以使用Update来执行以下操作:
使一个元素(出现)更改为另一个元素
禁用按钮,滑块,输入字段等。
更改按钮的文本
更改元素的文本或背景颜色
添加文本到滚动输出窗口
更改列表中的选择*等。
完成此操作的方式是通过适用于几乎所有Elements的Update方法。这是使用已更新的持久窗口的程序示例。
在某些程序中,这些更新是响应另一个元素而发生的。该程序采用微调器和滑块的输入值,并使用它们来调整文本元素的大小。Spinner和Slider在左侧,正在更改的Text元素在右侧。
# Testing async window, see if can have a slider
# that adjusts the size of text displayed
import PySimpleGUI as sg
fontSize = 12
layout = [[sg.Spin([sz for sz in range(6, 172)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin'),
sg.Slider(range=(6,172), orientation='h', size=(10,20),
change_submits=True, key='slider', font=('Helvetica 20')),
sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
sz = fontSize
window = sg.Window("Font size selector", layout, grab_anywhere=False)
# Event Loop
while True:
event, values= window.read()
if event is None:
break
sz_spin = int(values['spin'])
sz_slider = int(values['slider'])
sz = sz_spin if sz_spin != fontSize else sz_slider
if sz != fontSize:
fontSize = sz
font = "Helvetica " + str(fontSize)
window['text'].update(font=font)
window['slider'].update(sz)
window['spin'].update(sz)
print("Done.")
在事件循环内,我们使用那些Elements的键读取Spinner和Slider的值。例如,
values['slider']
是Slider元素的值。
如果Slider或Spinner更改,则此程序将更改所有3个元素。这是通过以下语句完成的:
window['text'].update(font=font)
window['slider'].update(sz)
window['spin'].update(sz)
请记住此设计模式,因为如果使用持久窗口,则将经常使用它。
它的工作原理如下。此
window[key]
表达式返回由提供的表示的Element对象
key
。然后,通过调用其
update
方法来更新此元素。这是Python的“链接”功能的另一个示例。我们可以使用长格式编写以下代码:
text_element = window['text']
text_element.update(font=font)
此练习的要点是,密钥是PySimpleGUI设计的关键。它们既用于读取窗口的值,也用于标识元素。如前所述,它们已在各种各样的地方使用。
定位元素(FindElement == Element == Elem == [])
用于查找元素的Window方法调用是:
FindElement
或缩短的版本
Element
甚至更短的版本(版本4.1+)
Elem
现在终于缩短为:window [key]
您会
window.Element(key)
在旧代码中找到模式。大约4.0之后的所有代码都使用缩短的
window[key]
符号。
ProgressBar /进度表
请注意,要更改进度条的进度,请致电
update_bar
,而不要致电
updat
e。对于将来的发行版,正在考虑对此进行更改。