学习资源:Trinket: PySimpleGUI Program
PySimpleGUI 是一个十分 Pythonic 的 GUI 框架。为了叙述方便将 PySimpleGUI 简记为 sg,窗口(Window)主题有超过 100 个可供选择,您可以使用函数 sg.preview_all_look_and_feel_themes()
查看所有主题。切换主题需要使用回调函数 sg.change_look_and_feel("主题名称")
。
import PySimpleGUI as sg
# 变换主题
sg.change_look_and_feel('Material1')
下面将讨论 PySimpleGUI 的几个核心组件,虽然每个组件的参数可能很多,但是我们只需要了解其核心参数即可,所以,下面的介绍仅仅列出函数的核心参数,比如像 sg.Window(title, layout, size=(5, 1))
这种形式。
1 sg.Popup 设计 I/O
sg.Popup
与 print
相当(用于输出(Output)),它创建了一个支持任意数量的任意 Python 支持的数据类型作为参数输入的 Window。变体有:sg.PopupOK
,sg.PopupOKCancel
,sg.PopupCancel
,sg.PopupError
,sg.PopupAutoClose
,sg.PopupYesNo
,sg.PopupTimed
。
关于输入(Input)可以使用 sg.PopupGetText
,sg.PopupGetFile
,sg.PopupGetFolder
获取用户的文本,文件,文件夹输入。
2 sg.Window 创建窗口
GUI 的设计目标一般都需要有一个用于和用户进行交互的窗口(Window)界面,为此 PySimpleGUI 提供 sg.Window 类创建窗口。使用方法:sg.Window(title, layout)
,其中 title
表示窗口的标题,layout
指定窗口的布局。
图1 提供了一个自定义 Window 布局以及如何使用其与用户交互的例子。下面对图1 的代码进行拆解。第 7~9 行定义了 Window 的布局,第 12 行定义了一个 Window,第 14~23 行定义了 Window 的交互方法,第 24 行将 Window 关闭以释放资源。其中 sg.Text
(sg.T == sg.Text == sg.Txt
)会将字符串打印到 Window,sg.Input
(sg.I == sg.InputText == sg.Input == sg.In
)用于获取用户的输入,sg.Button(sg.B == sg.Button
)表示 Window 的按钮。下面看看 Window.Read
的输出:
从图2 可以看出 values
是关键字为数字序号的 dict
,而 event
一般代表 Window 的按钮。然而,若 Window 中的 sg.Input
很多,我们仅仅依靠数字序号将十分不方便,为此我们需要传入 key
修改 dict
的关键字。具体实现见图3。
接下来您便可以使用关键字获取对应的表单数据。
3 在窗口显示用户输入
窗口 sg.Window
的元素可以通过类似于 dict
的方式进行更新及获取:
图4 显示了 sg.Window
的元素(也可称为“小部件”,“组件”)可以通过关键字(即 -OUTPUT-
)获取,使用 update
方法更新。
这里的sg.Window
的元素,即:
IN = window['-IN-']
IN
显示为:
获取该元素的值:
IN.get()
显示结果为:
'平安是福'
4 创建 To Do List
下面我们创建 To Do 表单:
图5 中 出现了复选项 sg.CBox
,它的返回值是 True
或者 False
,而 window.save_to_disk('ToDoList.out')
将 Window 的配置保存在磁盘,window.load_from_disk('ToDoList.out')
载入磁盘保存的 Window 配置。
5 创建菜单栏
先上代码:
import PySimpleGUI as sg
# ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
['&Edit', ['Paste', ['Special', 'Normal', ], 'Undo'], ],
['&Help', '&About...']]
relief_list = [sg.RELIEF_RAISED, sg.RELIEF_SUNKEN, sg.RELIEF_FLAT,
sg.RELIEF_RIDGE, sg.RELIEF_GROOVE, sg.RELIEF_SOLID]
def layout_relief(element):
return sg.Text(element,
size=(30, 1), justification='center',
font=("Helvetica", 25), relief=element)
layout = [[sg.Menu(menu_def, tearoff=True)]]
layout += [[layout_relief(element)] for element in relief_list]
window = sg.Window('Everything bagel', layout, default_element_size=(40, 1), grab_anywhere=False)
event, values = window.read()
window.close()
menu_def
定义了多级菜单栏,relief_list
展示了文本显示的样式,sg.Text
的参数 size=(30, 1)
表示文本框是宽30个字符,高1个字符。具体效果见图6:
6 方法名称简写
- 下拉列表:
Combo == InputCombo == DropDown == Drop
- 文本输入:
InputText == Input == In
- 复选框:
CBox == CB == Check
- 按钮:
Button== ReadButton == RButton == ReadFormButton
- 多行文本框:
Multiline == MLine
7 “选择器” 按钮
“选择器” 按钮("Chooser" Buttons)会弹出一个对话框用于选择 filename, date, color 等等。这些按钮直接可以通过名称便可以知道其代表的含义,即 FileBrowse
, FolderBrowse
, FileSaveAs
, FilesSaveAs
, CalendarButton
, ColorChooserButton
。比如使用 FolderBrowse
打开文件夹并将文件夹名称传递给 sg.In
,效果图见图7:
也可以自定义按钮:layout = [[sg.Button('My Button', key='_BUTTON_KEY_')]]
。
8 其他方法简介
- Listbox 示例:
layout = [[sg.Listbox(values=['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(30, 6))]]
,效果见图8:
- 多行文本输入输出:
sg.Multiline
,效果见图9:
- Slider(滑动条)
sg.Slider
,效果见图10:
- 单选
sg.Radio
与多选sg.Checkbox
,具体效果见图11:
需要注意的是 sg.Radio
的第2个参数是用来标识此选项是否归属于指定的 ID
。
- 上/下微调控件(An up/down spinner control)
sg.Spin
,效果图见图12:
- Progress Meter
import PySimpleGUI as sg
# layout the window
layout = [[sg.Text('A custom progress meter')],
[sg.ProgressBar(1000, orientation='h', size=(20, 20), key='progressbar')],
[sg.Cancel()]]
# create the window`
window = sg.Window('Custom Progress Meter', layout)
progress_bar = window['progressbar']
# loop that would normally do something useful
for i in range(1000):
# check to see if the cancel button was clicked and exit loop if clicked
event, values = window.read(timeout=10)
if event in ['Cancel', None]:
break
# update bar with loop value +1 so that bar eventually reaches the maximum
progress_bar.UpdateBar(i + 1)
# done with loop... need to destroy the window as it's still open
window.close()
效果图见图13:
7 Column
import PySimpleGUI as sg
# Demo of how columns work
# window has on row 1 a vertical slider followed by a COLUMN with 7 rows
# Prior to the Column element, this layout was not possible
# Columns layouts look identical to window layouts, they are a list of lists of elements.
window = sg.Window('Columns') # blank window
# Column layout
col = [[sg.Text('col Row 1')],
[sg.Text('col Row 2'), sg.Input('col input 1')],
[sg.Text('col Row 3'), sg.Input('col input 2')],
[sg.Text('col Row 4'), sg.Input('col input 3')],
[sg.Text('col Row 5'), sg.Input('col input 4')],
[sg.Text('col Row 6'), sg.Input('col input 5')],
[sg.Text('col Row 7'), sg.Input('col input 6')]]
layout = [[sg.Slider(range=(1,100), default_value=10,
orientation='v', size=(8,20)), sg.Column(col)],
[sg.In('Last input')],
[sg.OK()]]
# Display the window and get values
window = sg.Window('Compact 1-line window with column', layout)
event, values = window.read()
window.Close()
sg.Popup(event, values, line_width=200)
显示效果见图14:
- 运行
sg.main()
有惊喜,截图见图15:
- 创建一个控制面板(资料来源:)
代码(图片被转换为了Base64字符):
import PySimpleGUI as sg
"""
Creates a grid of buttons include of a column for scrolling
This window looks much like a control panel
NOTE - The SCROLLING using the mousewheel is known to have a bug in the tkinter port. You will need to have your mouse over the scrollbar to scroll with the mousewheel
"""
def GraphicButton(text:str, key:str, image_data):
text = text.replace('_', ' ')
button = sg.Button('', image_data=image_data, button_color=('white', '#9FB8AD'), font='Any 15', key=key, border_width=0)
text = sg.Text(text, font='Any 10', size=(15,1), justification='center',)
return sg.Column([[button],[text]], element_justification='c')
def main():
sg.ChangeLookAndFeel('GreenTan')
layout = [ [sg.Text('Control Panel. Click Abort to exit.')]]
layout += [[sg.Column([[GraphicButton(png_names[i+j*5], png_names[i+j*5] , png_images[i+j*5]) for i in range(2)] for j in range(7)], scrollable=True, size=(400,400))]]
window = sg.Window('Control Panel', layout, font='any 15', finalize=True)
while True: # ---===--- The event loop --- #
event, values = window.read()
print(event)
if event in ('Exit','Abort', None): # Exit button or X
break
window.close()
Abort = b"..."
...
vars = dir()
png_images = []
png_names = []
for var in vars:
png_images.append(eval(var))
png_names.append(var)
main()
显示效果图见图16: