使用 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
  • 从 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 的值后,最好检查变量中的值。与其使用 print 语句打印出来,不如坚持 GUI 的想法并将数据输出到窗口。

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 分钟浏览 Cookbook 以寻找大致匹配项。复制、粘贴并运行示例代码。然后,只需修改代码以匹配您的应用程序即可。

目标是使向软件添加体面的外观 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 (未验证)

如果您有功能想法或发现限制,我建议您在 GitHub 站点上写一份 Issue 并发布它。

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

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

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

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

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

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

回复 作者:PySimpleGUI

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

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

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

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

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

此外,根据 B3 段,他们希望青少年也遵守此要求,虽然我不认为法院会允许这样做,但这仍然会让孩子的父母花费大量资金才能弄清楚。

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

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

回复 作者:PySimpleGUI

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

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

回复 作者:Barlafuss (未验证)

PySimpleGUI 似乎非常适合我需要构建的小型 GUI 应用程序,但它必须基于 Python 2.7。下面的代码是我必须添加到 PySimpleGUI.py 顶部的所有代码,加上(如评论中所述)在 *() 中添加函数调用,用于每个 super() 调用(未在 Python 3 中测试!)。但是,一个让我感到困惑的“陷阱”是,我必须将方法调用中的每个 (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)

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

您是说您设法让 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

回复我自己:看起来我误解了参数类型基数。下面的链接显示“正式”关键字参数可以在 *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 时函数返回一个空元组的原因,因为 super() 调用在 v.3.x 下不需要任何参数。

回复 作者: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") 来制作自己的按钮。像这样的普通按钮不像内置按钮那样将回车键绑定到它们。如果您有进一步的问题,请在 github 网站上记录一个 issue (www.PySimpleGUI.com)

回复 作者:Curt Wuollet (未验证)

Creative Commons License本作品根据 Creative Commons Attribution-Share Alike 4.0 International License 许可。
© . All rights reserved.