继Python生态GUI框架之后,又听闻几款Python GUI工具类库,是故继续汇总整理。
Gooey
开源(GitHub,21.9K Star,1K Fork)Python GUI工具,能把命令行程序,一键包装成交互界面。通过装饰器,直接把命令行参数解析函数,渲染成可视化表单。
实战
安装:pip install gooey
示例:
py
from gooey import Gooey
import argparse
@Gooey(program_name="文本分析助手")
def main():
parser = argparse.ArgumentParser()
parser.add_argument("文件名")
parser.add_argument("--关键词", default="Python")
args = parser.parse_args()
print(f"正在分析文件: {args.文件名}")
print(f"搜索关键词: {args.关键词}")
if __name__ == "__main__":
main()
支持参数分组,实现功能模块化:
py
@Gooey(program_name="文件批处理工具")
def main():
parser = argparse.ArgumentParser()
输入组 = parser.add_argument_group("输入设置")
输入组.add_argument("--源目录", default="./input")
输入组.add_argument("--文件类型", default=".txt")
输出组 = parser.add_argument_group("输出设置")
输出组.add_argument("--输出目录", default="./output")
输出组.add_argument("--自动备份", action="store_true")
args = parser.parse_args()
print(f"源目录:{args.源目录}")
print(f"输出目录:{args.输出目录}")
支持直接渲染成单选框或复选框
py
from gooey import GooeyParser
@Gooey
defmain():
parser = GooeyParser()
parser.add_argument(
"模式",
choices=["快速扫描", "深度分析", "自定义"],
widget="RadioGroup"
)
parser.add_argument(
"--开启日志",
action="store_true",
widget="CheckBox"
)
args = parser.parse_args()
print(f"当前模式:{args.模式}")
print(f"日志状态:{args.开启日志}")
捕捉Print输出,并配合进度条
py
import time
from gooey import Gooey
@Gooey(progress_regex=r"^进度:(\d+)%$")
def main():
for i in range(101):
print(f"进度:{i}%")
time.sleep(0.05)
print("处理完成!")
Tkinter和PyQt功能强大,但开发成本高。写一个简单的文件处理工具,用Tkinter要布局、绑定事件,半天才能跑通。
Gooey的优势在于零布局开发,只需要写好命令行参数,界面自动生成。缺点是定制性弱,不适合做复杂交互的商业软件。
Pywinauto
项目首页,Windows系统下的开源(GitHub,6K Star,774 Fork)自动化GUI软件,可遍历窗口(对话框)和窗口里的控件,可控制鼠标和键盘输入。官方文档。
安装:pip install pywinauto
实例化Application对象时可传入backend参数,可选值:
- win32:默认,MFC、VB6、VCL、简单WinForms控件和大多数旧的Windows应用程序
- uia:WinForms、WPF、商店应用程序、Qt5、浏览器
检测某个Windows下的软件属于哪种框架,可使用Inspect(对应uia)和Spy++(对应win32)查看。
Application对象的主要方法
| 方法 | 常用参数 | 说明 |
|---|---|---|
start() |
cmd_line,timeout,retry_interval | 通过cmd命令启动一个软件(进程) |
connect() |
process,handle,path,timeout | 连接一个进程,一般是使用进程号(任务管理器可以看到) |
top_window() |
/ | 获取应用的顶层窗口 |
window() |
title,title_re,class_name,best_match | 获取单个窗口(WindowSpecification) |
windows() |
title,title_re,class_name | 获取多个窗口(UIAWrapper) |
is64bit() |
/ | 是否64位应用 |
cpu_usage |
interval | CPU占用率 |
wait_cpu_usage_lower() |
threshold,timeout | 等待CPU占率小于某个阈值 |
active() |
/ | 搜索返回一个激活的窗口 |
kill() |
soft | 结束进程 |
wait_for_process_exit() |
timeout,retry_interval | 等待进程结束 |
窗口,WindowSpecification对象,可通过Application对象的window()方法获取,参数可以是title、classname、best_match等,这都可以在inspect.exe上看到,inspect看到的Name其实对应的是window()的title参数。
WindowSpecification对象常用方法
| 方法 | 常用参数 | 说明 |
|---|---|---|
maximize() |
/ | 最大化窗口 |
minimize() |
/ | 最小化窗口 |
restore() |
/ | 恢复窗口 |
close() |
/ | 关闭窗口 |
get_show_state() |
/ | 获取窗口状态,0正常1最大化2最小化 |
was_maximized() |
/ | 当前是否最大化 |
draw_outline() |
colour,thickness | 给窗口画个框以便定位 |
print_control_identifiers() |
/ | 打印所有子窗口和子元素(会打印出对应的control_type) |
child_window() |
title,control_type | 获取子窗口 |
exists() |
timeout | 窗口是否存在 |
wait() |
wait_for_timeout | 等待窗口变成某个状态(exists,visible,enabled,ready,active) |
wait_not() |
wait_for_not_timeout | 等待窗口不处于某个状态(exists,visible,enabled,ready,active) |
控件:按钮(Button)、编辑栏(Edit)、树状视图(Tree View)、复选框(CheckBox)、对话框(Dialog)、工具栏(Toolbar)、状态栏(StatusBar)、列表框(ListBox)、窗格(Pane)、菜单(Menu)、菜单栏(MenuItem)、静态内容(Static)、工具提示(ToolTips)、列表控件(ListView)、单选框(RadioButton)、组合框(ComboBox)、选项卡控件(TabControl)、组框(GroupBox)、弹出菜单(PopupMenu)、头部(Header)等。
都有一个element_info的属性,访问之后会返回一个继承于ElementInfo的对象(UIAElementInfo或HwndElementInfo),比较重要的属性或方法如下
| 方法或属性 | 常用参数 | 说明 |
|---|---|---|
name |
/ | 元素的真实名(一般是title) |
visible |
/ | 元素是否可见 |
rich_text |
/ | 元素的全名 |
rectangle |
/ | 返回元素的位置以及宽高 |
class_name |
/ | 类名 |
enabled |
/ | 元素是否处于可用状态 |
parent |
/ | 返回父元素 |
children() |
title,title_re,class_name,best_match | 返回符合要求的子元素(列表) |
iter_children() |
title,title_re,class_name,best_match | 迭代符合要求的子元素(生成器) |
这些元素的element_info方法可获取元素的主要信息,还都被包装成Wrapper。BaseWrapper的方法基本上都是对ElementInfo进一步包装,部分方法
| 方法或属性 | 常用参数 | 说明 |
|---|---|---|
element_info |
/ | 返回当前元素的ElementInfo对象 |
from_point() |
x,y | 通过坐标查找ElementInfo |
class_name() |
/ | 类名,实际是调用element_info.class_name |
friendly_class_name() |
/ | 友好的类名,同上 |
window_text() |
/ | 元素的文本,实际是调用element_info.rich_text |
is_visible() |
/ | 元素是否可见,实际是调用element_info.visible |
is_enabled() |
/ | 元素是否可用,实际是调用element_info.enabled |
rectangle() |
/ | 元素的位置和宽高,实际是调用element_info.rectangle |
process_id() |
/ | 进程号,实际是调用element_info.process_id |
draw_outline() |
colour,thickness | 给当前元素画个框 |
click_input() |
button,coords,double | 鼠标操作,实际是调用mouse模块的_perform_click_input() |
type_keys() |
/ | 键盘操作,实际是调用keyboard模块的send_keys() |
每个控件元素都有对应的Wrapper,click_input()和type_keys()分别用于操作鼠标和键盘(输入)。
鼠标点击肯定离不开点击的位置,桌面就是一个坐标,左上角为坐标原点,往右是X轴正向,往下是Y轴正向。mouse模块用于鼠标操作,最核心_perform_click_input()私有方法,调用的方法都是基于此方法的封装方法
| 方法 | 参数 | 说明 |
|---|---|---|
click() |
button,coords | 单击鼠标某个键 |
double_click() |
button,coords | 双击鼠标某个键 |
right_click() |
coords | 单击鼠标右键 |
move() |
coords | 移动鼠标 |
press() |
button,coords | 按下鼠标 |
release() |
button,coords | 放开鼠标 |
scroll() |
coords,wheel_dist | 滚动鼠标滚轮 |
wheel_click() |
coords | 单击鼠标滚轮 |
参数说明:
- 参数
button默认值都是left,即鼠标左键,可选值:left、right、middle、move、wheel、x - 参数
coords默认值都是元组(0, 0),元组里的两个整数分别是X、Y轴的值 - 参数
wheel_dist表示滚动的距离,大于0是向上滚动,小于0是向下滑动
键盘操作主要是按下键盘上的按键,相关方法在keyboard模块,最主要的是send_keys()方法,第一个参数keys是需要按下的按键,其他参数比如说with_spaces、with_tabs、with_newlines、turn_off_numlock、set_foreground、vk_packet,都是布尔值
| 按键 | 符号 | 说明 |
|---|---|---|
| Shift | VK_SHIFT | 上档键 |
| Ctrl | VK_CONTROL,VK_LCONTROL,VK_RCONTROL | Ctrl键,左右Ctrl键 |
| Alt | VK_MENU | Alt键 |
| Windows | VK_LWIN,VK_RWIN | 左右win键 |
| Space | VK_SPACE | 空格键 |
| backspace | BACKSPACE | 退格键 |
| enter | ENTER | 回车键 |
| esc | ESC | 退出键 |
| table | VK_TAB | 制表键 |
| left,right,up,down | VK_LEFT,VK_RIGHT,VK_UP,VK_DOWN | 上下左右方向键 |
| f1~f24 | VK_F1,VK_F2...VK_F24 | f1到f24 |
| capslock | CAPSLOCK | 大写键 |
说明:
- 使用按键时需要搭配大括号,按下回车键是
'{ENTER}' - Windows平台默认发送虚拟按键,以
VK_开头的按键,都是虚拟按钮,如果不想使用虚拟按钮可以把VK_前缀去掉,把send_keys()的vk_packet参数改为False即可 - 单个按键按下抬起还不够,往往需要组合键。修饰符,在大括号里可使用
down、up控制按键什么时候按下和抬起,后面加上数字,表示多少次 - 使用
down、up修饰不够简洁,提供简化写法,使用+代替{VK_SHIFT},使用^代替{VK_CONTROL},使用%代替{VK_MENU}。
PyQuery
开源(GitHub,2.4K Star,187 Fork)类jQuery语法Python库,将前端jQuery那套选择器语法搬到Python里。
和CSS选择器一模一样,可通过类名、ID、标签名等多种方式精确定位到想要的元素。
.items()方法返回一个生成器,可高效地遍历多个元素,可动态添加、修改DOM结构。
py
from pyquery import PyQuery as pq
# 创建PyQuery对象
html = '<div class="container"><h1>Hello World</h1><p>Welcome to PyQuery</p ></div>'
doc = pq(html)
# 获取标题文本
title = doc('h1').text()
# 查找所有段落
paragraphs = doc('p')
print('段落数量:', len(paragraphs))
# 包含链接和图片的HTML
web_content = '''
<nav>
Home
About
</nav>
<main>
< img src="banner.jpg" alt="网站横幅">
</main>
'''
doc = pq(web_content)
# 获取第一个链接的地址
first_link = doc('nav a:first-child')
print('首页链接:', first_link.attr('href'))
# 获取活跃链接的文本
active_link = doc('a.active')
print('活跃标签:', active_link.text())
# 获取图片信息
image = doc('img')
print('图片地址:', image.attr('src'))
print('图片描述:', image.attr('alt'))
优势是语法简洁,特别适合有前端基础的开发者。相比BeautifulSoup,其API更直观;相比正则表达式,它处理HTML更稳定。但面对特别复杂的解析需求时,可能需要结合XPath。建议日常网页数据提取优先考虑PyQuery。
JustPy
官网,开源(GitHub,1.3K Star,96 Fork)Python Web框架,基于Starlette和Vue,允许开发者完全使用Python操作Vue组件,直接在后端定义前端的交互逻辑,无需编写一行JS。
安装:pip install justpy
示例:
py
import justpy as jp
def click_demo(request):
wp = jp.WebPage()
# 定义计数显示区域
count_div = jp.Div(text="当前点击数:0", a=wp, classes="text-h5")
def increment(self, msg):
# 读取并更新文本中的数字
old_num = int(count_div.text.split(":")[1])
count_div.text = f"当前点击数:{old_num + 1}"
# 绑定按钮点击事件
jp.Button(text="点我 +1", a=wp, click=increment, classes="bg-blue-500 text-white p-2")
return wp
jp.justpy(click_demo)
相比于传统的Django/Flask+JS模式,JustPy学习成本极低,特别适合算法工程师快速搭建原型。
其劣势在于项目生态相对年轻,目前社区已处于停止维护状态,对于复杂的高并发场景,建议还是回归原生JS或其他成熟框架。
Maliang
项目首页,基于Tkinter的开源(GitHub,1.1K Star,49 Fork)轻量级UI框架,通过完全在Canvas上绘制所有UI元素的方式,实现媲美现代设计语言的视觉效果,同时保持极小的体积和出色的性能。
实战
安装:pip install maliang
pip install maliang[opt]
采用类似其他现代框架的设计,几行代码就能生成一个带有标题和尺寸的窗口。核心优势在于所有UI元素都通过Canvas绘制。内置明暗两套主题,并支持一键切换。开发者还可为组件分别定义深色/浅色模式下的样式。内置流畅的动画系统,支持移动、缩放、颜色渐变等多种动画类型,让界面交互更加生动。
py
import maliang
from maliang.animation import MoveAnimation, ColorAnimation
from maliang.shapes import Rectangle, Circle
from maliang.theme import set_color_mode
app = Maliang(
width=800,
height=600,
title="我的第一个Maliang应用"
)
app.add_label("Hello,Maliang!", x=100, y=100, size=24)
app.run()
app = Maliang(600, 400, "图形绘制示例")
rect = Rectangle(
x=100, y=100,
width=200, height=100,
radius=15, # 圆角半径
fill="#4a6fa5", # 填充颜色
outline="#2c3e50"# 边框颜色
)
app.add_shape(rect)
circle = Circle(
x=400, y=150,
radius=50,
fill="#e74c3c"
)
app.add_shape(circle)
app.run()
app = Maliang(500, 400, "主题切换演示")
# 创建带样式的按钮
button = app.add_button(
text="切换主题",
x=200, y=150,
width=100, height=40,
style={
"fg": ("#ffffff", "#000000"), # 深色/浅色模式下的文本颜色
"bg": ("#4a6fa5", "#e0e0e0"), # 深色/浅色模式下的背景颜色
"border_radius": 8
}
)
def toggle_theme():
current = app.get_color_mode()
set_color_mode("dark"if current == "light"else"light")
button.on_click(toggle_theme)
app.run()
app = Maliang(600, 400, "动画演示")
box = app.add_rectangle(100, 150, 80, 80, fill="#3498db")
# 创建移动动画
move_anim = MoveAnimation(
widget=box,
offset=(300, 0), # 向右移动300像素
duration=1000, # 持续时间1000毫秒
loop=True # 循环播放
)
# 创建颜色渐变动画
color_anim = ColorAnimation(
element=box,
colors=("#3498db", "#e74c3c"),
duration=1000,
loop=True
)
move_anim.start()
color_anim.start()
app.run()
相比原生Tkinter,Maliang界面美观度大幅提升、动画支持完善。相比PyQt,体积极小、无需学习复杂API。
不足:作为新兴框架,组件库丰富度不如成熟方案。
NiceGUI
WhakerPy
项目首页,开源(GitHub)轻量级零依赖(除Python标准库)的Web应用框架,用Python代码来写HTML。最早是从SPPAS(语音处理软件)里抽出来,其安装程序、官网都是基于WhakerPy搭建,Cued也是基于WhakerPy搭建。PyPi。
基于Python逻辑动态生成页面,自带HTTPD服务器和bakery响应系统,能本地运行启动后看效果;能保存成静态文件,随时部署。
安装:pip install WhakerPy
py
HTMLNode(None, None, "h1", value="这是个标题")