Gooey库入门

Gooey

将(几乎)任何Python3控制台程序转换为GUI程序,仅需(最少)一行代码。

Gooey使用方法与Argparse库极其相似,是Argparse库的直接替代。

我们先从Argparse开始

Argparse库是用来给Python脚本传入位置参数选项的库(就像Shell脚本一样)
就像这样python test.py -option arg1 arg2

使用方法

库名:argparse
创建一个传参容器对象parser1
parser1 = argparse.ArgumentParser()
添加一个位置参数,其名字为a,属性为整数
parser1.add_argument("a", type=int)
创建参数对象,每个参数都是它的一个属性
args = parser1.parse_args()
调用a参数
print(args.a)
Argparse库的优势在于,如果调用脚本时没有使用参数,那么会有详细的回显提示:

1
error: the following arguments are required: a

它还会自动添加–help内容

1
2
3
4
5
6
7
usage: mycode.py [-h] a

positional arguments:
a

optional arguments:
-h, --help show this help message and exit

你也可以手动在实例化函数的参数中添加脚本描述,扩充help内容
parser1 = argparse.ArgumentParser(description='a test script')
parser1.add_argument("a", type=int, help="this is arg 1")

add_argument的一些设置参数

  1. name=””
    就是位置参数的名字,位于第一位时可以省略name=
  2. nargs=num
    参数的数量,超过1个时,多个参数组成参数列表。特殊的值包括*任意个,?0或1个,+至少1个。
  3. type=int|bool|string|float|…
    参数的数据类型,不解释。
  4. help=””
    有关参数的提示内容,不解释。
  5. action=””
    参数的动作,会在解析到参数时进行触发,一共有六种:
    store保存参数值,可能会先将参数值转换成另一个数据类型。若没有显式指定动作,则默认为该动作。
    store_const保存一个被定义为参数规格一部分的值,而不是一个来自参数解析而来的值。这通常用于实现非布尔值的命令行标记。
    store_ture/store_false保存相应的布尔值。这两个动作被用于实现布尔开关。
    append将值保存到一个列表中。若参数重复出现,则保存多个值。
    append_const将一个定义在参数规格中的值保存到一个列表中。
    version打印关于程序的版本信息,然后退出。
  6. default=
    参数的默认值,不解释。

快速开始

安装指南

最简单的安装方法就是通过pip
pip install Gooey
或者你也可以把Gooey项目clone到本地
git clone https://github.com/chriskiehl/Gooey.git
然后运行 setup.py
python setup.py install

基本用法

通过用一个简单的装饰器就可以将Gooey附到任何一个使用argparse传参的函数上(通常是main函数),然后Gooey就可以将你所有需要用到的参数可视化为文本框、选择框甚至是文件选择框。

1
2
3
4
5
6
from gooey import Gooey

@Gooey <---就这么简单!
def main():
parser = ArgumentParser(...)
# 剩下的代码

可以在装饰器中传参以配置不同的风格和功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 一些选项
@Gooey(advanced=Boolean, # 设置是否显示高级选项
language=language_string, # 可通过json文件配置语言
auto_start=True, # 跳过所有选项页面并立刻执行程序
target=executable_cmd, # 显式设置子进程可执行文件的参数
program_name='name', # 默认程序名
program_description, # 默认程序描述
default_size=(610, 530), # 默认窗口尺寸
dump_build_config=False, # 备份Gooey配置json文件
load_build_config=None, # 加载一个Gooey配置json文件
)
def main():
parser = ArgumentParser(...)
# 剩下的代码

Gooey会尽最大可能自动选择合适的控件来呈现GUI,但是如果想要手动调节,也是可以的。你可以用GooeyParser函数替代ArgumentParser函数进行实例化,然后手动添加元素

1
2
3
4
5
6
7
8
from gooey import Gooey, GooeyParser

@Gooey
def main():
parser = GooeyParser(description="测试程序!")
parser.add_argument('Filename', widget="FileChooser")
parser.add_argument('Date', widget="DateChooser")
...

原理

Gooey可以通过装饰器的方式附在任何使用了argparse库的函数上。

1
2
3
4
@Gooey
def my_run_func():
parser = ArgumentParser(...)
# 剩下的代码...

在运行时,它会将add_argument函数中的所有参数传递给ArgumentParser,然后进行解包并根据指定的action分配控件,最后在执行parse_args函数时自动组成GUI。

Mappings:

Gooey尽最大可能根据提供的信息进行控件的映射,目前对应关系如下:

| Parser Action | 对应控件 |
| - | - | - |
| store | TextCtrl/TextField |
| store_const | CheckBox |
| store_true | CheckBox |
| store_false | CheckBox |
| version | CheckBox |
| append | TextCtrl/TextField |
| count | DropDown |
| Mutually Exclusive Group | RadioGroup |
| choice | DropDown |

当没有提供可以参考的参数时,由于默认actionstore,所以程序默认使用文本输入框控件TextCtrl

GooeyParser

如果默认的映射关系不能满足你的需求,你也可以手动设置控件,只需要将ArgumentParser函数替换为GooeyParser,两者之间唯一的区别是后者能让你手动指定控件类型。
GooeyParser函数允许你给实例设置额外的参数widget以指定控件类型。除此之外,你不需要修改任何argparse相关的代码!
示例

1
2
3
4
5
6
7
from argparse import ArgumentParser
...

def main():
parser = ArgumentParser(description="测试程序")
parser.add_argument("name", help="this is help", action="store")
...

按照这段代码,Gooey会生成一个普通的文本框。

有以下几个值得注意的点:

  1. Python脚本文件名对应的就是程序名。
  2. description参数值会显示在标题上。
  3. name和help会显示在对应的交互控件旁边,一般是上方。

如果你使用GooeyParser并提供了widget参数的值为FileChooser,那么你可以显示一个更加友好的文件选择控件:

1
2
3
4
5
6
 from gooey import GooeyParser
....

def main():
parser = GooeyParser(description="测试程序")
parser.add_argument("name", help="this is help", action="store", widget="FileChooser")

自定义增强控件

控件名 含义
DirChooser 目录选择
FileChooser 文件选择
MultiFileChooser 多文件选择
FileSaver 文件保存
MultiFileSaver 多文件保存
DateChooser/TimeChooser 日期/时间选择
PasswordField 密码输入
Listbox 列表选择
BlockCheckbox 带有文字描述内容的复选框,使用gooey_options.checkbox_label指定文字内容
ColourChooser 选色器
FilterableDropdown 可输入式下拉列表
IntegerField 数字选择
DecimalField 小数选择
Slider 滑动条

国际化

Gooey支持国际化设置,只需要在@Gooey装饰器中加上一个参数:

1
2
3
@Gooey(language='russian')
def main():
...

所有程序文本都记录在外部的json文件中,所以要添加新的语言支持,只需要将一些键值对添加到gooey/languages/目录下。

全局设置

要设置Gooey的外观和功能,只需要向装饰器中传入一些参数即可:

Parameter Summary
encoding 字符的编码(默认:’utf-8’)
advanced 显示完整的选项菜单
auto_start 跳过所有选项立刻执行程序
language gooey/languages目录中选择一种语言
target Gooey的调用程序,默认使用Python
suppress_gooey_flag 如果修改target的话应当开启以防Gooey注入额外的参数
program_name 程序名,默认使用从sys.argv[0]获得的文件名
program_description 设置程序描述,默认使用ArgumentParser中的描述
default_size 默认窗口尺寸
fullscreen 全屏启动Gooey
dump_build_config 保存选项到json文件
load_build_config 加载json选项文件
image_dir 自定义图标/图片路径
language_dir 语言文件路径
disable_stop_button 运行时禁用Stop按钮
show_stop_warning 运行被用户中止时发送警告
force_stop_is_error 显示成功/失败提示后立刻退出
show_success_modal 成功后是否显示总结回显
show_failure_modal 失败后是否显示总结回显
show_restart_button 是否显示Restart按钮
run_validators Gooey执行程序前是否认证
use_cmd_args 将所有运行时提供的位置参数替换为Gooey选项中的默认值
return_to_config 设为真,Gooey会在成功执行后回到选项页面
disable_progress_bar_animation 禁用进度条
show_time_remaining 禁用剩余时间显示
hide_time_remaining_on_complete 完成后禁用剩余时间显示
requires_shell 运行程序时是否需要命令行位置参数
shutdown_signal 按下Stop按钮时发送的终止信号
navigation 设置Gooey显示风格,可选项:TABBED, SIDEBAR
sidebar_title 使用SIDEBAR时,设置边栏标题,默认为”Actions”
show_sidebar 使用SIDEBAR时,是否显示边栏
header_height 标题高度
header_show_title 是否显示标题
header_show_subtitle 是否显示子标题
terminal_font_family 字体名称
terminal_font_weight 字体粗细(constants.FONTWEIGHT_NORMAL, constants.FONTWEIGHT_XXX)
terminal_font_size 字体大小
menus 显示自定义菜单
clear_before_run 执行前清理上一次的输入内容

自定义样式

以下四个参数可以用于设置不同的样式

show_sidebar=True show_sidebar=False navigation='TABBED' tabbed_groups=True

组合输入
默认搭配argparse使用Gooey时,输入被分为位置参数和选项参数。但是这并不总是用户想要的划分方式。你可以使用add_argument_group()函数将任意输出搭配为一个组合对象。

1
2
3
4
5
parser = ArgumentParser()
search_group = parser.add_argument_group(
"选项",
help="设置选项"
)

你也可以把其它参数加入组合中:

1
2
3
4
search_group.add_argument(
'--query',
help='设置内容'
)

这些参数会在UI中组合出现

执行模式

Gooey有一系列的呈现模式。

高级模式

默认的显示模式是“完整”或者说“高级”模式。这种模式下分为两种布局,由Gooey转换的命令决定。
第一种布局为平铺布局,这种布局符合大部分CLI程序(比如Curl, FFMPEG)的逻辑,一般情况下这种布局就可以了。
另一种布局是行布局。这种布局适合有多种子工具,每种都有自己的参数和选项的程序(比如Git)。这种布局会在某个位置(边栏或选项卡)显示可选操作,主界面显示给当前操作提供的参数。这种布局很适合同时提供多种功能的小程序。
每一种布局都会把传参容器作为独立的GUI组件呈现出来。

设置布局风格
布局风格由是否存在subparser决定,所以,如果你想使用行布局,首先确保使用advanced模式,然后在argparse代码中添加一个subparser

1
2
3
@gooey(advanced=True)
def main():
...

基础模式

这种模式尤其适合习惯于终端程序的用户。
只需要将@Gooey装饰器的advanced参数设为False即可

1
2
3
@gooey(advanced=False)
def main():
...

无选项模式

这种模式不提供让用户输入选项的界面,直接进入显示结果的界面并开始执行程序,适用于一部分直接执行的脚本。
启用这一模式,在@Gooey装饰器中设置auto_start=True

1
2
3
@Gooey(auto_start=True) 
def main ():
...

窗口菜单

你可以给Gooey添加一个自定义的菜单。
菜单在@Gooey装饰器中作为一组映射列表给出:

1
@Gooey(menu=[{}, {}, ...])

每组映射由两对键值对组成:

  1. name菜单组的名字
  2. items菜单组中每个项目的内容

你可以设置任意数量的菜单组,它们都会作为列表传给@Gooey装饰器的menu参数

1
2
3
@Gooey(menu=[{'name': 'File', 'items: []},
{'name': 'Tools', 'items': []},
{'name': 'Help', 'items': []}])

菜单组中的项目也是键值对的映射列表。它们的键由其type决定,但是有两个键必须设置。

  1. type设置点击菜单项的行为,同时也决定它的其它键
  2. menuTitle此菜单项的名字

目前支持四种菜单项类型:

  • AboutDialog
  • MessageDialog
  • Link
  • HtmlDialog

AboutDialog
是程序的关于对话框。它会显示程序的信息,包括名字,版本和许可证等等。

可选的内容:

  • name
  • description
  • version
  • copyright
  • license
  • website
  • developer

示例:

1
2
3
4
5
6
7
8
9
10
11
{
'type': 'AboutDialog',
'menuTitle': 'About',
'name': 'Gooey Layout Demo',
'description': 'An example of Gooey\'s layout flexibility',
'version': '1.2.1',
'copyright': '2018',
'website': 'https://github.com/chriskiehl/Gooey',
'developer': 'http://chriskiehl.com/',
'license': 'MIT'
}

MessageDialog
是通用的信息对话框,你可以通过此对话框显示任何种类的信息,比如警告。

内容:

  • message必须,信息的内容
  • caption可选,信息的标题

示例:

1
2
3
4
5
6
{
'type': 'MessageDialog',
'menuTitle': 'Information',
'message': 'Hey, here is some cool info for ya!',
'caption': 'Stuff you should know'
}

Link
用于将用户带去外部的网站,这一选项会唤出默认浏览器。

内容:

  • url完整的URL

示例:

1
2
3
4
5
{
'type': 'Link',
'menuTitle': 'Visit Out Site',
'url': 'http://www.example.com'
}

HtmlDialog
用户可以拷贝的,HTML格式的信息对话框。

内容:

  • caption可选,对话框的标题
  • html必须,在对话框中显示的HTML内容

示例:

1
2
3
4
5
6
7
8
9
10
11
12
{
'type': 'HtmlDialog',
'menuTitle': 'Fancy Dialog!',
'caption': 'Demo of the HtmlDialog',
'html': '''
<body bgcolor="white">
<img src=/path/to/your/image.png" />
<h1>Hello world!</h1>
<p><font color="red">Lorem ipsum dolor sit amet, consectetur</font></p>
</body>
'''
}

一个完整的示例
两个菜单组,各自带有不同的菜单项:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
@Gooey(
program_name='Advanced Layout Groups',
menu=[{
'name': 'File',
'items': [{
'type': 'AboutDialog',
'menuTitle': 'About',
'name': 'Gooey Layout Demo',
'description': 'An example of Gooey\'s layout flexibility',
'version': '1.2.1',
'copyright': '2018',
'website': 'https://github.com/chriskiehl/Gooey',
'developer': 'http://chriskiehl.com/',
'license': 'MIT'
}, {
'type': 'MessageDialog',
'menuTitle': 'Information',
'caption': 'My Message',
'message': 'I am demoing an informational dialog!'
}, {
'type': 'Link',
'menuTitle': 'Visit Our Site',
'url': 'https://github.com/chriskiehl/Gooey'
}]
},{
'name': 'Help',
'items': [{
'type': 'Link',
'menuTitle': 'Documentation',
'url': 'https://www.readthedocs.com/foo'
}]
}]
)

自定义图标

Gooey默认自带了六个图标。但是你也可以用自己的图片/图标对其进行替换,只需要告诉Gooey在初始化时搜索的路径即可。
@Gooey装饰器指定image_dir参数:

1
2
3
@Gooey(program_name='自定义图标测试', image_dir='/path/to/my/image/directory')
def main():
...

Gooey会根据文件名自动发现图片并进行替换。比如,举例来说,要替换程序图标,只需要在图片目录下添加一个名为config_icon.png的文件即可。
以下为可以覆盖的文件名:

  • program_icon.png
  • success_icon.png
  • running_icon.png
  • loading_icon.gif
  • config_icon.png
  • error_icon.png

打包

打包Gooey项目也很简单。
一种简单的办法是下载这个build.spec文件并放到程序目录下,然后编辑文件内容,修改APPPNAMEname这两项以对应你的项目,然后修改pathex项以指定程序的根目录,然后执行pyinstaller -F --windowed build.spec,就可以进行打包了。
你也可以看看详细教程.