使用 PySimpleGUI 轻松地为您的程序和脚本添加 GUI

在五分钟内创建一个自定义 GUI。
335 位读者喜欢这篇文章。

很少有人像运行 .exe 文件一样,通过双击 .py 文件来运行 Python 程序。当典型的用户(非程序员类型)双击 .exe 文件时,他们希望它弹出一个可以交互的窗口。虽然可以使用标准的 Python 安装来使用 tkinter 创建 GUI,但很少有程序这样做。

如果打开一个 Python 程序到一个 GUI 中非常容易,甚至完全的初学者都可以做到,会怎么样呢? 会有人在意吗? 会有人使用它吗? 很难回答,因为到目前为止,构建自定义 GUI 并不容易

在为 Python 程序/脚本添加 GUI 的能力方面,似乎存在差距。完全的初学者只能使用命令行,而许多高级程序员不想花费时间编写 tkinter GUI。

GUI 框架

Python 不乏 GUI 框架。 Tkinter、WxPython、Qt 和 Kivy 是一些主要的软件包。此外,还有许多简化版的 GUI 软件包,它们“包装”了主要的软件包之一,包括 EasyGUI、PyGUI 和 Pyforms。

问题在于,初学者(经验少于六周的人)甚至无法学习最简单的主要软件包。 这使得包装器软件包成为一个潜在的选择,但对于大多数新用户来说,构建自定义 GUI 布局仍然是困难或不可能的。 即使可能,包装器仍然需要大量的代码。

PySimpleGUI 试图通过提供一个超级简单、易于理解的 GUI 接口来解决这些 GUI 挑战,该接口可以轻松定制。即使是许多复杂的 GUI,在使用 PySimpleGUI 时也只需要不到 20 行代码。

秘诀

PySimpleGUI 对新手来说更优越的原因在于,该软件包包含了用户通常需要编写的大部分代码。按钮回调由 PySimpleGUI 处理,而不是用户的代码。 初学者很难掌握函数的概念,期望他们在最初几周就理解回调函数是不现实的。

对于大多数 GUI,排列 GUI 小部件通常需要几行代码……每个小部件至少需要一两行代码。 PySimpleGUI 使用一个“自动打包器”来自动创建布局。 无需 pack 或 grid 系统来布局 GUI 窗口。

最后,PySimpleGUI 以巧妙的方式利用 Python 语言结构,缩短了代码量,并以直接的方式返回 GUI 数据。 在表单布局中创建小部件时,它是就地配置的,而不是在几行代码之外。

什么是 GUI?

大多数 GUI 做一件事:从用户那里收集信息并返回它。 从程序员的角度来看,这可以概括为一个函数调用,如下所示

button, values = GUI_Display(gui_layout)

大多数 GUI 期望的是单击的按钮(例如,确定、取消、保存、是、否等)以及用户输入的值。 GUI 的本质可以归结为单行代码。

这正是 PySimpleGUI 的工作方式(对于简单的 GUI)。 当调用显示 GUI 时,除非单击关闭表单的按钮,否则什么都不会执行。

还有更复杂的 GUI,例如在单击按钮后不会关闭的 GUI。 示例包括机器人的远程控制界面和聊天窗口。 这些复杂的表单也可以使用 PySimpleGUI 创建。

快速创建一个 GUI

什么时候 PySimpleGUI 有用? 立即,每当您需要 GUI 时。 创建和尝试 GUI 只需不到五分钟。 创建 GUI 最快的方法是从 PySimpleGUI Cookbook 复制一个。 遵循以下步骤

  • 找到一个看起来与您想要创建的 GUI 相似的 GUI
  • 从 Cookbook 中复制代码
  • 将其粘贴到您的 IDE 中并运行它

让我们看看这本书中的第一个食谱。

import PySimpleGUI as sg

# Very basic form.  Return values as a list
form = sg.FlexForm('Simple data entry form')  # begin with a blank form

layout = [
          [sg.Text('Please enter your Name, Address, Phone')],
          [sg.Text('Name', size=(15, 1)), sg.InputText('name')],
          [sg.Text('Address', size=(15, 1)), sg.InputText('address')],
          [sg.Text('Phone', size=(15, 1)), sg.InputText('phone')],
          [sg.Submit(), sg.Cancel()]
         ]

button, values = form.LayoutAndRead(layout)

print(button, values[0], values[1], values[2])

这是一个大小合适的表单。

PySimpleGUI data entry form

如果您只需要收集几个值,并且它们基本上都是字符串,则可以复制此食谱并对其进行修改以满足您的需要。

您甚至可以在五行代码中创建一个自定义 GUI 布局。

import PySimpleGUI as sg

form = sg.FlexForm('My first GUI')

layout = [ [sg.Text('Enter your name'), sg.InputText()],
           [sg.OK()] ]

button, (name,) = form.LayoutAndRead(layout)

PySimpleGUI form from 5 lines of code

在五分钟内创建一个自定义 GUI

如果您有一个简单的布局,您应该能够通过修改 Cookbook 中的代码,在不到五分钟的时间内在 PySimpleGUI 中创建一个自定义布局。

在 PySimpleGUI 中,小部件被称为元素。 这些元素的拼写与您在 Python 代码中键入它们的拼写完全相同。

核心元素

Text
InputText
Multiline
InputCombo
Listbox
Radio
Checkbox
Spin
Output
SimpleButton
RealtimeButton
ReadFormButton
ProgressBar
Image
Slider
Column

快捷方式列表

PySimpleGUI 也有两种类型的元素快捷方式。 一种类型只是完全相同元素的其他名称(例如,T 而不是 Text)。 第二种类型使用特定的设置配置元素,从而避免您指定所有参数(例如,Submit 是一个文本为“Submit”的按钮)

T = Text
Txt = Text
In = InputText
Input = IntputText
Combo = InputCombo
DropDown = InputCombo
Drop = InputCombo

按钮快捷方式

许多常用按钮已实现为快捷方式。 这些包括

FolderBrowse
FileBrowse
FileSaveAs
Save
Submit
OK
Ok
Cancel
Quit
Exit
Yes
No

还有一些用于更通用的按钮功能的快捷方式。

SimpleButton
ReadFormButton
RealtimeButton

这些是您可以在 PySimpleGUI 中选择的所有 GUI 小部件。 如果某个小部件不在这些列表中,则它不会出现在您的表单布局中。

GUI 设计模式

在 GUI 中,往往不会改变的是设置和显示窗口的调用。 元素的布局是程序之间发生变化的地方。

这是上面示例的代码,删除了布局

import PySimpleGUI as sg

form = sg.FlexForm('Simple data entry form')
# Define your form here (it's a list of lists)
button, values = form.LayoutAndRead(layout)

大多数 GUI 的流程是

  • 创建表单对象
  • 将 GUI 定义为列表的列表
  • 显示 GUI 并获取结果

这些是您在 PySimpleGUI 的设计模式中看到的逐行内容。

GUI 布局

要创建您的自定义 GUI,首先将您的表单分解为行,因为表单是一次定义一行的。 然后从左到右依次放置一个元素。

结果是一个“列表的列表”,如下所示

layout = [  [Text('Row 1')],
            [Text('Row 2'), Checkbox('Checkbox 1', OK()), Checkbox('Checkbox 2'), OK()] ]

此布局生成此窗口

PySimpleGUI custom data entry form

显示 GUI

完成布局并复制了设置和显示表单的代码行后,就可以显示表单并从用户那里获取值了。

这是显示表单并提供结果的代码行

button, values = form.LayoutAndRead(layout)

表单返回两个值:单击的按钮的文本和用户输入到表单中的值的列表。

如果显示示例表单,并且用户除了单击确定按钮之外什么都不做,则结果将是

button == 'OK'
values == [False, False]

复选框元素返回 True 或 False 的值。 因为复选框默认为未选中状态,所以返回的值均为 False。

显示结果

获得 GUI 的值后,最好检查变量中包含的值。 让我们坚持使用 GUI 想法,而不是使用 print 语句打印它们,而是将数据输出到窗口。

PySimpleGUI 有许多消息框可供选择。 传递到消息框的数据显示在一个窗口中。 该函数接受任意数量的参数。 您可以简单地指示您想要在调用中看到的所有变量。

PySimpleGUI 中最常用的消息框是 MsgBox。 要显示上一个示例的结果,请编写

MsgBox('The GUI returned:', button, values)

将它们放在一起

现在您已经了解了基础知识,让我们将包含尽可能多的 PySimpleGUI 元素的表单放在一起。 此外,为了使其外观更好,我们将“外观”更改为绿色和棕褐色的配色方案。

import PySimpleGUI as sg

sg.ChangeLookAndFeel('GreenTan')

form = sg.FlexForm('Everything bagel', default_element_size=(40, 1))

column1 = [[sg.Text('Column 1', background_color='#d3dfda', 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.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25))],
    [sg.Text('Here is some text.... and a place to enter text')],
    [sg.InputText('This is my text')],
    [sg.Checkbox('My first checkbox!'), sg.Checkbox('My second checkbox!', default=True)],
    [sg.Radio('My first Radio!     ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")],
    [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, 3)),
     sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)],
    [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),
     sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=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='#d3dfda')],
    [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(), sg.Cancel()]
     ]

button, values = form.LayoutAndRead(layout)
sg.MsgBox(button, values)

这看起来似乎有很多代码,但是尝试直接在 tkinter 中编写相同的 GUI 布局,您将很快意识到它有多么小。

PySimpleGUI advanced custom data entry form

最后一行代码打开一个消息框。 看起来像这样

PySimpleGUI custom message box

消息框调用的每个参数都显示在新的一行上。 消息框中有两行文本; 第二行非常长,并且换行了很多次

花点时间将结果值与 GUI 配对,以了解如何创建和返回结果。

向您的程序或脚本添加 GUI

如果您有一个使用命令行的脚本,则不必为了添加 GUI 而放弃它。 一个简单的解决方案是,如果在命令行中没有给出任何参数,则运行 GUI。 否则,像今天一样执行命令行。

只需要这种逻辑

if len(sys.argv) == 1:
	# collect arguments from GUI
else:
    # collect arguements from sys.argv

快速启动并运行 GUI 的最简单方法是从 PySimpleGUI Cookbook复制和修改其中一个食谱。

玩得开心! 为你那些厌倦了手工运行的脚本增添乐趣。 花费 5 或 10 分钟玩一下演示脚本。 你可能会发现已经存在一个完全符合你需求的脚本。 如果没有,你会发现创建自己的脚本很简单。 如果你真的迷失了,你只会投入 10 分钟的时间。

资源

安装

PySimpleGUI 在所有运行 tkinter 的系统上都能工作,包括 Raspberry Pi,它需要 Python 3

pip install PySimpleGUI

文档

标签

24 条评论

感谢您撰写这篇文章。 我将永远是一个初学者,因为我对严肃的编程没有兴趣。 只是喜欢涂鸦。 在过去的几周里,我一直在考虑尝试运行一些 Windows 下可用的非常简单的“编程”/创意包。

甚至 HTA 也闪过我的脑海。 一直在考虑在 WINE 或虚拟化下进行此操作。 Linux 根本不迎合简单... 即使 bash 也可能过度设计。 PySimpleGUI 看起来很完美(对于某些解决方案)。 这可能有助于引诱我更认真地使用 python。

这是对一个伟大解决方案的极好介绍,它一直是我面临的一个令人烦恼的问题。 我的代码只有两个小问题。

1. 由于该库需要 Python 3,因此第一行必须是

#! /usr/bin/python3

2. 同样,对于 Python 3,你必须使用 pip3 来安装。 否则它最终会进入 Python2 库集合。

现在,将它与 psycopg2 结合起来以在数据库中插入和更新记录的最有效方法是什么? 还要考虑到表已经进行了某种程度的规范化,因此每个记录可能会分布在两到三个不同的表中,并且某些字段的值列表必须从静态数据表中获取。

如果问题/应用程序有一个 GUI 或可以从 GUI 中受益,那么 PySimpleGUI 是一个不错的起点。 如果它不合适,你可以快速排除它并继续前进。

如果项目看起来可能是一个候选者,请花 2 分钟浏览使用指南以寻找粗略的匹配项。 复制、粘贴并运行 Recipe 代码。 然后,只需修改代码以匹配你的应用程序即可。

目标是使向软件添加一个像样的外观 GUI 变得微不足道。 如果可以让初学者轻松上手,那么在教育中更早地向学生介绍 GUI 会很好。

我对你的建议是立即行动并尝试各种东西。 让某些东西运行。 让任何东西运行。 然后修改它甚至重新开始。 重点是你拥有一个工作环境,一张空白的画布。

看过之后,它对我不起作用。 虽然从静态表中检索 id 和显示文本非常容易,但我只需要在列表框中显示文本,但返回与所选内容匹配的 id,因为这将存储在新记录中。 也许这会使它成为未来版本的一个有用的增强功能?

回复 ,作者:PySimpleGUI

如果“表”是你需要交互的基本内容,那么 PySimpleGUI 还无法提供以交互方式执行此操作的方法。

显示表格相对容易,结果也很好
https://user-images.githubusercontent.com/13696193/44960497-c667fd80-ae…

如果你想尝试,这是代码

layout = [[sg.T('Table Test')]]
for i in range(20)
row = [sg.T(f'Row {i} ', size=(10,1))]
layout.append([sg.T(f'{i}{j}', size=(4,1), background_color='white', pad=(1,1)) for j in range(10)])
sg.FlexForm('Table').LayoutAndRead(layout)

有两个缺失的功能使该软件包不是数据库类型操作的最佳选择
1. 表格
2. 可滚动窗口

据我所知,tkinter 中没有“表格”小部件。 我已经看过一些建议的解决方案,但还没有任何解决方案脱颖而出。 第一步是使 Column Element 可滚动。

应该注意的是,PySimpleGUI 的主要任务是实现“简单 GUI”。

回复 ,作者:Robert McConnell (未验证)

如果你有功能想法或发现限制,我建议你写一个 Issue 并将其发布到 GitHub 网站上。

我对你在 Listbox 上尝试的操作感到困惑。 在这些事情上进行交流的最佳方式是通过 GitHub。

回复 ,作者:Robert McConnell (未验证)

过程很简单。 我有一个永远不会改变的铁路表。 它包括一个键(id),长名称和短名称。 所以我在 CSV 格式中最重要的两个记录是

1, Pennsylvania Railroad, PRR
2, Coudersport and Port Allegany Railroad, CPA

我做一个 SQL 选择 id 和短名称以获得一个选择列表,然后在列表框中显示它。 一旦用户选择,我需要返回 id 以存储在新记录中。

我无法接受 GitHub 服务条款,所以这甚至不是一个遥远的可能性。

回复 ,作者:PySimpleGUI

明白了。 刚刚完成了可滚动 Column Elements 的创建,这为表和你描述的应用程序铺平了道路。

是什么 GitHub 服务条款阻止了你? 也许它被错误地陈述了。

回复 ,作者:Robert McConnell (未验证)

哪些条款? 我几乎不知道从哪里开始。 但让我给你前三名。

1 Q 节。赔偿:如果某个白痴决定因为感觉受到轻视,或者因为他想窃取我的作品而起诉我,我将不得不卖掉我拥有的一切,以支付任何可以回应投诉的律师的聘用费。 我不可能在这种情况下赔偿任何人。 如果你不认为这种情况可能发生,请阅读 JMRI 的历史。

此外,根据 B3 段,他们希望青少年遵守此要求,虽然我不认为法院会允许这样做,但孩子的父母要弄清楚这一点仍然会非常昂贵。

2. B4 段说,当网站被黑客入侵时,用户仍然要对漏洞负责,即使他们无法控制后端安全性。 这对于没有实际谈判的标准商业合同来说太典型了。 它变成了一个单方面的文件,所有风险都转嫁到用户身上。 这让我面临着一个要么接受要么离开的决定,我选择离开它。

3. R 节未能以任何有意义的方式定义“重大变更”,仅列出了一个薄弱的例子。 这为律师留下了太多的回旋余地,他们完全有可能决定出售所有收集到的客户信息,在半夜完成对网页的更改,并在太阳升起之前将钱存入银行。 既然他们被微软拥有,我不得不认为这是一个非常真实的可能。

回复 ,作者:PySimpleGUI

它能在 KDE/Plasma 环境下工作吗? 刚刚尝试将一个示例 + PySimpleGUI.py 复制到目录中并运行,但我只看到一个非常小的“十字”,像鼠标指针一样,仅此而已 ...

我将在 GitHub 上打开一个 issue。 请访问并输入更多信息,以便可以进行调试(Python 版本、Linux 版本等)。

回复 ,作者:Barlafuss (未验证)

已访问。
问题主要通过 Robert McConnell 的建议解决(谢谢!)。

回复 ,作者:PySimpleGUI

PySimpleGUI 似乎非常适合我需要构建的小型 GUI 应用程序,但它_必须_基于 Python 2.7。 以下代码是我必须添加到 PySimpleGUI.py 顶部的所有内容,以及(如注释中所述)在 *() 中添加函数调用,用于每个 super() 调用(未经 Python 3 测试!)。 但是,让我感到困惑的一个“陷阱”是,我必须将方法调用中的每个(args)移动到命名(“关键字 args”)参数之后的位置。 这绝对不符合 Python 约定,但它可以修复错误 ...

import platform

sVsn = platform.python_version()[0]

if sVsn == '2'
__metaclass__ = type # Python v.2.X 所必需

def fSuprArgs(self)
return () if sVsn != '2' else (self.__class__, self)

# 将 *(fSuprArgs(self)) 作为参数放置在对 super() 的每次调用中

你是说你成功地让 PySimpleGUI 在 Python 2.7 上运行了????!

如果是这样,请将文件发布到 GitHub(或你选择的任何其他地方)。 这个请求不时出现。 我本周早些时候收到一个。

回复 ,作者:Noah F San (未验证)

是的,这是我项目的要求。 只需将上面的代码添加到 PySmpleGUI.py 的顶部,在每个 super() 中插入函数调用,如下所示:super(*(fSuprArgs(self))),将所有 *args 移动到参数列表中它出现的最后一个位置,你就完成了。

小心,缩进会在此网页上损坏...

我已经根据 CC-BY-SA 许可了这些更改,无论这意味着什么,请随意使用。

请注意:仅使用 Python 2.7.12 测试过,未经 Python 3 测试!

此外,我发现有很多小部件感到困惑,因为它们期望颜色值元组作为第一个参数,所以我总是填充(1,1),这可以防止其他错误。

回复 ,作者是 PySimpleGUI

回复我自己:看来我误解了参数类型的基数。下面的链接表明,'formal' 关键字参数_可以_位于 *args 之前,但 *args 不能位于 **kwargs 之前,当一起使用时。因此,防止错误的更改仍然是合法的 Python,但我当然不知道为什么它会起作用。

http://www.network-theory.co.uk/docs/pytut/KeywordArguments.html

回复 ,作者:Noah F San (未验证)

我进行了所有这些更改,并将 *args 移动到所有函数的末尾。

而且,它_奏效了_!至少在我尝试的一个简单表单上是这样。 还有更多的工作要做。 我对这个结果感到震惊! 我非常感谢你!!

回复 ,作者:Noah F San (未验证)

最后一条消息...

感谢你的鼓励和编码帮助,我刚刚将 PySimpleGUI27 发布到 PyPI

我做了很多测试,但我无法测试 PyPI 版本。它应该运行良好。这是你做的一件了不起的事情!

回复 ,作者:Noah F San (未验证)

很抱歉我没有更清楚地说明 v.2.7 更改的预期工作方式。虽然我没有使用 v.3.x 进行测试,但相同的 PySimpleGUI 代码_应该_可以在任何一个版本下工作。 这就是为什么当版本 != 2.x 时,该函数返回一个空元组,因为在 v.3.x 下 super() 调用不需要任何参数。

回复 ,作者是 PySimpleGUI

如何添加覆盖应用程序整个窗口的背景图像? 我在任何地方都看不到这个功能。 只能更改颜色。

主题也不起作用。

sg.ChangeLookAndFeel('BluePurple')
没有任何反应。 也尝试更改颜色变量。

如果你是在 Mac 上,你不会看到任何变化。 你会看到打印出这条消息
*** Mac 平台不支持更改外观 ***'

请确保在布局定义之前调用 ChangeLookAndFeel。 布局需要知道这些颜色。

你还可以使用你想要的各个颜色选项调用 SetOptions。 它不会被 Mac 阻止调用。 阻止外观调用的原因是按钮颜色在 Mac 上不起作用。

如果问题仍然存在,请随时在 github 上提交一个 issue。

回复 ,作者是 Mike Kell (未验证)

有没有办法防止多行输入框溢出到操作系统
如果用户点击回车键?
Raspbian Raspberry Pi

既然你没有提到任何崩溃,听起来你的 Read 正常返回并且你只是退出了程序。 可能发生的是你正在使用 Submit() 或 OK() 按钮。 默认情况下,这些按钮有一个名为 bind_return_key 的参数设置为 true。 如果你正在使用内置按钮,那么尝试添加参数 ... bind_return_key=False... 到调用中。 或者你可以通过调用 Button("Submit") 来切换到创建你自己的按钮。 像这样的普通按钮不像内置按钮那样将 Enter 键绑定到它们。 如果你有更多问题,请在 github 网站上记录一个 issue (www.PySimpleGUI.com)

回复 ,作者是 Curt Wuollet (未验证)

知识共享许可协议本作品采用知识共享署名 - 相同方式共享 4.0 国际许可协议授权。
© . All rights reserved.